View Full Version : Lagarith vs. HD YV12 Rec.709 content
fvisagie
13th September 2015, 20:40
How do you guys handle HD YV12 Rec.709 content with the Lagarith encoder? Of the 17-odd yuv420-type formats VirtualDub 1.10.4 provides, it seems the Lagarith encoder only supports "YCbCr (Rec.601) Limited 4:2:0 -". No full-range formats, no dedicated interlaced formats, and no Rec.709-based formats.
What does this imply for working with HD content in Lagarith - is this the time to abandon it? Or, is it still chroma-safe to work with YV12 -> RGB32 -> YV12 round-trips, provided one uses Rec.601 conversions both before and after? Any other ideas?
Thanks,
François
poisondeathray
13th September 2015, 21:08
It depends on your workflow, which programs and decoders you are using. But it can work fine
If you use avisynth or vapoursynth for everything, you control precisely where the conversions are occurring and how (interlaced vs progressive, which matrix) .
If you use common NLE's , YUV lossless codecs usually get converted to RGB incorrectly (superbrights/darks get clipped)
raffriff42
13th September 2015, 22:37
You can control the conversion in VirtualDub too. Don't convert to RGB unless you really have to (eg, certain vdub filters).
Here's something (virtualdub forum (http://forums.virtualdub.org/index.php?act=ST&f=15&t=21459&hl=709,or,rec709&st=15#entry93237))"phaeron" Posted: May 14 2013, 12:54 AM
The YV12 FOURCC corresponds to Rec. 601, and attempting to push Rec. 709 through it results in a situation where programs reading it have no idea which color space they are dealing with and thus you get color handling errors in the pipeline. Therefore, if you do have bogus YV12 data that is actually Rec. 709, you need to re-alias it to the 709 format so VirtualDub knows what it is actually dealing with.
fvisagie
14th September 2015, 09:20
Here's something (virtualdub forum (http://forums.virtualdub.org/index.php?act=ST&f=15&t=21459&hl=709,or,rec709&st=15#entry93237))"phaeron" Posted: May 14 2013, 12:54 AM
The YV12 FOURCC corresponds to Rec. 601, and attempting to push Rec. 709 through it results in a situation where programs reading it have no idea which color space they are dealing with and thus you get color handling errors in the pipeline. Therefore, if you do have bogus YV12 data that is actually Rec. 709, you need to re-alias it to the 709 format so VirtualDub knows what it is actually dealing with.
That is something very useful you're showing me here :-). I was not aware of the alias filter.
If you use avisynth or vapoursynth for everything, you control precisely where the conversions are occurring and how (interlaced vs progressive, which matrix) .
Thanks, that's what I hoped would work.
In other words, for perfectly symmetrical conversions (not mixing 601 and 709 coefficients) around VirtualDub filtering when VirtualDub is not doing any conversion ('-' = process boundary):
{"709 YV12"AVS"RGB32"}-{VirtualDub filtering}-{"RGB32"AVS"709 YV12"}-{encode}
Or, perhaps less desirably, would having VirtualDub do both conversions work correctly as follows?
{"709 YV12"AVS}-{"601 YV12""aliased to 709 YV12""RGB32"VirtualDub filtering"RGB32""709 YV12""aliased to 601 YV12"}-{"709 YV12"AVS}-{encode}
For space-saving I would probably opt for the latter, rendering YV12 from VirtualDub to disk. Seeing that aliasing can unambiguously inform VirtualDub of colour coefficients, what are the pros and cons of of Avisynth vs. VirtualDub doing the inital 709 YV12-to-RGB32 conversion?
Is it correct to say that working with VirtualDub's YV12 render would require some care, always to ensure it is actually treated as Rec.709 YV12? And the same care would need to be taken with the encoder, ensuring it recognises or is told it is working with Rec.709 YV12?
PS. VirtualDub's broken interlaced YV12 chroma treatment should not be an issue here, because I foresee all HD content being progressive.
poisondeathray
14th September 2015, 15:13
I tested vdub's color space input/output options and alias filter about a year ago - they didn't work properly then but it might be fixed by now. I just ran test charts, color bars through various combinations and checked the output.
fvisagie
15th September 2015, 13:00
I tested vdub's color space input/output options and alias filter about a year ago - they didn't work properly then but it might be fixed by now. I just ran test charts, color bars through various combinations and checked the output.
How did you check the output - compare results with equivalent processing in Avisynth, or some other way?
poisondeathray
15th September 2015, 15:51
How did you check the output - compare results with equivalent processing in Avisynth, or some other way?
Yes, I'm very thorough with these types of tests. I make sure I know exactly what decoder, splitter, etc.. is being used at what stage. I also test other compression and different uncompressed fourcc versions in case the handling is slightly different. I use known colorbar and calibration videos (known YUV and RGB values). Avisynth's default conversion is a slightly "off" compared to other methods (this is known and discussed in other threads, possibly due to 8bt and rounding), but vdub's was way way off. It might be fixed by now
shekh
15th September 2015, 17:13
I did some test 1 year ago: compared yuv->rgb by VirtualDub vs ffmpeg. Also compared to this picture passed through to x264 and decoded again - no difference.
I wasnt very thorough however, just wanted to get rid of low/full range hell and it worked.
poisondeathray
15th September 2015, 17:22
I did some test 1 year ago: compared yuv->rgb by VirtualDub vs ffmpeg. Also compared to this picture passed through to x264 and decoded again - no difference.
I wasnt very thorough however, just wanted to get rid of low/full range hell and it worked.
ffmpeg uses Rec601 and standard range (ie. rec601 matrix, progressive) by default, just like vdub, unless you use the proper range , matrix (and interlaced) flags for -vf scale, or sws flags
in_range
out_range
in_color_matrix
out_color_matrix
https://ffmpeg.org/ffmpeg-filters.html#scale-1
https://ffmpeg.org/ffmpeg-scaler.html#scaler_005foptions
shekh
15th September 2015, 17:41
Yes thats not problem because my source is tagged "full range 709" by camera and I applied that.
I am curious to test it again if you point me some encoded/decoded references.
poisondeathray
15th September 2015, 17:47
Yes thats not problem because my source is tagged "full range 709" by camera and I applied that.
I am curious to test it again if you point me some encoded/decoded references.
What is the "problem" ? Can you be more specific ?
"Tagged" full range in the camera metadata doesn't necessarily mean content is full range
If your camera is recording YUV, but has excursions into "super whites and darks" (ie.. <16, >235) , then a standard range RGB conversion will clip them. Most consumer cameras actually record 16-255 anyways
If you use the wrong 601, vs 709, the colors will be slightly off when viewing (esp. skin tones)
shekh
15th September 2015, 18:19
"Tagged" full range in the camera metadata doesn't necessarily mean content is full range
If your camera is recording YUV, but has excursions into "super whites and darks" (ie.. <16, >235) , then a standard range RGB conversion will clip them. Most consumer cameras actually record 16-255 anyways
If you use the wrong 601, vs 709, the colors will be slightly off when viewing (esp. skin tones)
Agree.
What is the "problem" ? Can you be more specific ?
Forgive me my english.
You told there was problem. I replied with "it works for me".
So I dont have or cant see a problem.
poisondeathray
15th September 2015, 18:27
The problem is clipping data (not lossless) when letting ffmpeg or vdub do the default conversion, and/or wrong matrix (wrong colors) when doing YUV<=>RGB conversions. (YUV<=>RGB isn't lossless in the first place, so I'm talking about additional losses to that)
But if the conversion is symmetrical, the color issue is less of a problem (still the rounding issues, slightly off, but neglible most of the time). What I mean by symmetrical is you use the "wrong" 601 matrix to convert from YUV source to RGB, and the "wrong" 601 matrix to convert back to YUV - you get almost the same colors as what you started with. In effect, "2 wrongs" almost make a "right' :) . If you do it at higher bit depth than the default 8, you get even closer to what you started with (more precise, less rounding error). But the clipping issue still occurs for superbright/superdark data with the Rec matrices. You won't "see" the loss on a display because a Rec matrix is normally used to view in the first place. But if you look at a waveform monitor, all those values >235, <16 will be lost (clipped) , or you can measure the loss with metrics
shekh
15th September 2015, 18:46
I compared RGB images copied from vdub, so "2 wrongs effect" was not involved :)
So do you have example where vdub decodes yuv->rgb, all setup right, yet the result is wrong? Or I have lost what are we talking about
poisondeathray
15th September 2015, 18:53
I compared RGB images copied from vdub, so "2 wrongs effect" was not involved :)
So do you have example where vdub decodes yuv->rgb, all setup right, yet the result is wrong? Or I have lost what are we talking about
now it's confusing
There would 1 wrong in that case, because it will have been converted to RGB using 601 (+/- the data loss you didn't see)
You would compare that by doing the proper RGB conversion using 709 using a known method like avisynth (you should see the color difference)
(It might be "fixed" by now in vdub , where you can specify a YUV to RGB conversion using 709 . It definitely was not working about a year ago, and definitely uses 601 by default, even now)
shekh
15th September 2015, 19:12
now it's confusing
(It might be "fixed" by now in vdub , where you can specify a YUV to RGB conversion using 709 . It definitely was not working about a year ago, and definitely uses 601 by default, even now)
I thing I got it. I assumed using correct colorspace setting, either by alias filter or otherwise. Btw it seems that code did not change somewhere from 2012 but I am not historian :)
Default setting is responsibility of input driver, can be quite different from 601.
poisondeathray
15th September 2015, 19:28
I thing I got it. I assumed using correct colorspace setting, either by alias filter or otherwise. Btw it seems that code did not change somewhere from 2012 but I am not historian :)
Default setting is responsibility of input driver, can be quite different from 601.
What I'm saying tests I did with vdub ~1 year ago didn't yield the correct results either with different combinations of alias filter, or the input/output csp settings (video=>color depth=>other , there is a list of many choices)
I would argue that the input driver ideally should leave the input as is. If you want to apply a transformation later (e.g. colormatrix or convert to RGB , whatever) that should be separate. Usually that is the case in vdub anyway, but some input filters might apply a "hidden" conversion
When you "see" the preview in vdub, it's being converted to RGB . When you take a screenshot with vdub with default settings, it's using the default Rec.601 to convert to RGB. Ideally you should be able to use some combination of input/output and alias to instead convert to RGB using Rec709 (ie to have some additional control) . Those options definitely didn't work correctly in the past. I don't know if they work now.
shekh
15th September 2015, 21:34
I would argue that the input driver ideally should leave the input as is
Totally agree. But correct way of doing this is to tag yuv format as 709 if it is tagged as 709 in the file. There is no conflict here.
(VirtualDubs 709/601 and FR format variations are essentially tags).
We can talk about my driver instead of abstract one :)
I tried to preserve image bytes and pass correct tags when possible. So that if tags are available there is no intervention needed (no need to select input format or alias filter) and otherwise at least the bytes are not destroyed before reaching filters etc.
When you take a screenshot with vdub with default settings, it's using the default Rec.601 to convert to RGB
If it is tagged as 709, then it is always converted to rgb as 709, whichever reason for conversion (at least latest code works that way).
fvisagie
16th September 2015, 11:11
I use known colorbar and calibration videos (known YUV and RGB values).
Thanks.
unless you use the proper range , matrix (and interlaced) flags for -vf scale, or sws flags
in_range
out_range
in_color_matrix
out_color_matrix
https://ffmpeg.org/ffmpeg-filters.html#scale-1
https://ffmpeg.org/ffmpeg-scaler.html#scaler_005foptions
Your prescience is impressive! I was planning to look into ffmpeg's colour-space handling next.:)
Even when no specified or implied resizing is required, is the 'scale' filter the correct/only way of specifying input and output formats and ranges?
poisondeathray
16th September 2015, 14:23
You don't have to actually do any scaling of dimensions with -vf scale - just set width, height =-1
There are other ways, such as using -pix_fmt (e.g. yuvj420p "j" would be full range) , sws flags, -vf colormatrix (to change in YUV, it's like avisynth's colormatrix). I don' t know if any of them are the "proper" way
But it's always changing in ffmpeg land - it's hard to keep up unless you're actively checking it. At one point those scale options didn't work properly, but maybe 1/2 year ago they did, and there was at least 1 build in between where it didn't work. There are slight "gotchas" for each method, sometimes quality issues. For example, even though -vf colormatrix is ported from avisynth, it tends to yield lower quality. And produces slightly different results from ffmbc's -vf colormatrix yet all are derived from the same code! Theoretically it should have given the same results. All the ffmpeg conversions are 8bit currently. Higher quailty way, without a doubt, is to use higher bit depth conversion in vapoursynth or stack16 in avisynth. It's easy to demonstrate how your output values deviate more compared to output when using any of the 8bit conversion methods
fvisagie
16th September 2015, 19:53
Thank you.
fvisagie
17th September 2015, 20:19
It seems VirtualDub nailed it in the meantime. In my testing, frame-served colour rendering came out near perfect, and rendering to file was identical to equivalent Avisynth processing (at least for the video format I tested, namely YV12 Rec.709 full-range video). The difference between frame-serving and file rendering behaviour can probably be explained by the fact that in the latter case VirtualDub was able to complete a symmetrical conversion and achieve "two wrongs making a right", as you guys foresaw. ;)
I used Avisynth to generate test input for VirtualDub, then used Avisynth to read back its output, which was then compared to both the input and another Avisynth script simulating VirtualDub's processing. In all cases, Avisynth's simulation was identical to the input (bar the usual very slight chroma blurring on some boundaries). In the case of frame-serving, VirtualDub's output differed by only 1 in only one of the 3 octets some of the time, and when rendering to file its output was identical to Avisynth, with the same amount of chroma blurring as the Avisynth simulation.
Because I'll be working with over- and under-shoot ([0,255]) video, I tested only that. AvsPmod was used as the Avisynth client, and its YUV -> RGB conversion was set to PC levels for the full-range video. VirtualDub was configured for 4:2:0 planar YCbCr (YV12) input and output colour depths.
For test input into VirtualDub I used
PCrange = true
matrix = PCrange ? "PC.709" : "Rec709"
ColorBarsHD(pixel_type="YV24").Trim(0, -1) # Create "HD YV12 Rec.709 full-range" source (super-black in pluge pulse)
ConvertToYV12(matrix=matrix, interlaced=false)
Subtitle(matrix)
Subtitle("VirtualDub source", align=1)
For frame-serving, VirtualDub's filter graph was configured as follows:
alias format (709, full)
convert format (RGB32)
knowing that it would truncate that to RGB24 for frame-serving.
VirtualDub's output was then read by this script
AVISource("C:\Users\fvisagie\Documents\Working\vdcat\preview.avi", audio=true)
Subtitle("VirtualDub output", align=3)
and compared to the source and this script
PCrange = true
VDout = "frameserver" # "frameserver" / "file"
matrix = PCrange ? "PC.709" : "Rec709"
ColorBarsHD(pixel_type="YV24").Trim(0, -1) # Create "HD YV12 Rec.709 full-range" source (super-black in pluge pulse)
ConvertToYV12(matrix=matrix, interlaced=false)
ConvertToRGB32(matrix=matrix, interlaced=false) # Simulate VirtualDub RGB32 filtergraph round-trip
VDout == "frameserver" ? ConvertToRGB24(matrix=matrix, interlaced=false) : \
VDout == "file" ? ConvertToYV12(matrix=matrix, interlaced=false) : \
Assert(false, """Invalid 'VDout' value """"+VDout+""""""")
Subtitle(matrix)
Subtitle("Avisynth simulation", align=1)
For rendering to file, VirtualDub's filter graph was configured as follows:
alias format (709, full)
convert format (RGB32)
convert format (YV12-709-FR)
alias format (601, limited)
That last line made all the difference.
For evaluating this output, VDout was set to "file" in the simulation script, not that it made any difference.
fvisagie
17th September 2015, 20:28
In follow-up, to prevent VirtualDub asymmetrically converting YV12 when frame-serving, presumably pre-converting its input to RGB32 would work.
EDIT: It does.
poisondeathray
18th September 2015, 00:13
Thanks for posting the follow up
I cannot reproduce your results with a full range YUV colorbars input video (converted from RGB source using PC.709) using this
alias format (709, full)
convert format (RGB32)
convert format (YV12-709-FR)
alias format (601, limited)
What did you have video=>color depth set to ?
vdub 1.10.5 test7 , avs is loaded with AVIFileInputDriver (default) . File=>file information should say "Internal DIB Decoder" .
Also, I can confirm the newest FFInputDriver does read 709 flags correctly for AVC sources , and the RGB conversion is correct
fvisagie
18th September 2015, 12:09
I cannot reproduce your results with a full range YUV colorbars input video
And with synthesized input as I used?
What did you have video=>color depth set to ?
For file rendering, 4:2:0 planar YCbCr (YV12) (i.e. the standard old YV12 RC.601 limited range) for both input and output.
vdub 1.10.5 test7
I am using 1.10.4, although one would hope for no regressions to a newer version.
avs is loaded with AVIFileInputDriver (default) .
I've been using the auto-detect File.Open mode, which presumably selected the same driver.
File=>file information should say "Internal DIB Decoder" .
This may be a significant difference. Some time ago I installed the ancient Helix YV12 codec. Memory fails as to precisely why, but presumably to enable Windows programs to open raw video files. Around the same time, I unchecked all VirtualDub Options.Preferences.AVI.Directly encode... and Prefer internal... options. Because those settings haven't created any problems, I've just continued with them...
Therefore, in this case, for YV12 input File.Information reports "Helix YV12 (YV12)". If I find the time to retest with internal decoding and find differences, I'll let you know.
Also, I can confirm the newest FFInputDriver does read 709 flags correctly for AVC sources , and the RGB conversion is correct
If I understand this correctly, this enables VirtualDub to open AVC (and other ffmpeg-supported format) files directly, and to do so correctly wrt. YV12 709 content, meaning that RGB32 conversion round-trips end up done correctly? That would be fantastic. I'd have to check that my camera files correctly flag 709 etc., so I'll probably leave looking into this for another day. Thanks for mentioning this.
Just to make it clear, in the testing I did above there was no objective external reference as is the ideal. I simply read off AvsPmod mouse pointer pixel values, which meant that the benchmark was "being as good as Avisynth + AvsPmod". I did take care, though, to ensure AvsPmod was configured for the correct colour-space range and that Avisynth treated content correctly.
fvisagie
18th September 2015, 12:26
For the ColorBarsHD() YV12 source above, there is no difference in behaviour between the Helix and internal YV12 codecs that I could detect - with the given VirtualDub filtergraph, they both do the round-trip perfectly. I did check File.Information each time ;).
Pardon the insulting question :o, in VirtualDub you did select Video.Full processing mode?
poisondeathray
18th September 2015, 14:53
The problem was I had video=>color depth set to auto. Manually setting to 4:2:0 planar fixed it
For the FFInputDriver - I only tested 1 trip to RGB. But it should be possible given the alias and convert filters
raffriff42
18th September 2015, 18:54
ColorBarsHD(pixel_type="YV24").Trim(0, -1) # Create "HD YV12 Rec.709 full-range" source (super-black in pluge pulse)
BTW, ColorBarsHD is not actually full range, per the ColorBars doc (http://avisynth.nl/index.php/ColorBars).
To confirm it, try this test:ColorBarsHD(pixel_type="YV24") ## or any other ColorBars/ColorBarsHD expression
(IsRGB) ? RGBAdjust(analyze=true) : ColorYUV(analyze=true]
There is no range conversion when converting from YV24->YV12, only YUV<->RGB conversions do this.
fvisagie
19th September 2015, 10:24
The problem was I had video=>color depth set to auto. Manually setting to 4:2:0 planar fixed it
That's great to hear.
ColorBarsHD(pixel_type="YV24").Trim(0, -1) # Create "HD YV12 Rec.709 full-range" source (super-black in pluge pulse)
BTW, ColorBarsHD is not actually full range, per the ColorBars doc (http://avisynth.nl/index.php/ColorBars).
We're in agreement there. I should have grouped the double-quotes more tightly around "full-range", i.e. pseudo-full-range. It referred only to the super-black pluge pulse as actually mentioned in above link:The pluge (see below) goes to -4 IRE; 'blacker than black'.
To confirm it, try this test:ColorBarsHD(pixel_type="YV24") ## or any other ColorBars/ColorBarsHD expression
(IsRGB) ? RGBAdjust(analyze=true) : ColorYUV(analyze=true]
The pluge pulse shows up in the luma minimum of 12.
poisondeathray
19th September 2015, 17:08
That's great to hear.
Totally my fault - because its stated right there in your clear instructions! :)
fvisagie
20th September 2015, 15:12
Meh, I could just as well have posted the configuration as a VD configuration file :). Seeing as I didn't even cover encoder (Lagarith) settings, which - if incorrect - could have caused unexpected Rec.601-based conversions right there.
Regardless, I'm very grateful for your confirmation that I wasn't overlooking something that could have invalidated these seemingly great results.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.