Video Scope Calibration

To avoid confusion please use standard nomenclature. I assume by “pure white” you mean 255. By “legal range” I assume you mean limited range (16 - 235).

I’ve already made those checks and have quadruple checked them with Shotcut, videozoom, VLC and my eyedropper program as well as checking the flags in MediaInfo, as I explained. So I have actually quintuple checked them if you count MediaInfo.

[quote=“Austin, post:60, topic:19672”]
If those scopes showed Y 235, then the file does not have full-range Y values.[/quote]

Again, I have quintuple checked all of this.

You’re confused. Both the full- and limited-range files (separate files) have 0,16,235,255 and the flags have been checked with MediaInfo. The video levels have been checked as described above. Is that enough checking for you? There’s nothing wrong with the test files. The problem is with the ffplay scope.

Have you checked the flags of your test files? Are you running MediaInfo?

If you want, I can share both test files with you.

That would help a lot. Let’s do that. It should be small enough to post here in a zip file.

Since the only test we’re concerned about (to my knowledge) is “what’s the Shotcut IRE of Y 255 in a limited range file”, please let me know which file is used for that specific test so I don’t get confused.

The files are clearly named with “full” and “limited” in the file names so you can’t go wrong. I will upload them to my hosting service and send you the URL later today.

Not just 255 but all of the values. The other problem is with the ffplay scope reversing “full” and “limited” range.

Again, are you running MediaInfo?

https://mediaarea.net/en/MediaInfo

The problem I’ve had with some video players is that they force 235 to 255 and there is no way to defeat this behavior, so you’re not getting a true representation of the video data. That’s why I had to revert to an earlier version of VLC.

No, I use ffprobe. It says the range flag of FullValuesLimitedFlag.mp4 is limited. The digital waveform says the values are 0, 16, 235, 255.

Our issue here is not the range flag. It’s the numerical Y values in the data itself. I’ve attached a zip file with my source image, FFmpeg commands, resultant test video, and the digital waveform of the video for your analysis. Shotcut video zoom shows the right-most swatch as Y 255 and 108 IRE.

FullValuesLimitedFlag.zip (5.2 KB)

Does “above” include a digital waveform like this? What were the values of the stair steps?

ffmpeg -i Window_limited.mp4 -frames:v 1 -vf waveform=scale=digital:flags=numbers+dots:display=overlay:g=green:o=0.25 Window_limited_scope.png

But I can’t find any post revealing the values that were found. Was the whitest swatch in the test image at Y 235 or Y 255 in the Shotcut video zoom scope? (I can’t call it 235 or 255 because that’s the value we’re trying to figure out.)

[quote=“Austin, post:65, topic:19672”]
Our issue here is not the range flag.[/quote]

Right, however, the ffplay scope reverses the IRE values for full and limited files. I need backing on this before filing a bug report.

The values are 0,16,235,255. Four squares from left to right. The Shotcut preview pane has the correct values for both full and limited. As noted, the Shotcut SCOPE is not handling limited files correctly. See above for ffplay. VLC has the correct values but it is not a scope, just a viewer. The eyedropper program I wrote in PureBasic agrees with Shotcut’s video zoom and it calculates Y from RGB and converts Y to IRE units.

Clear now? I’m not on my regular computer now so this will have to wait a while.

In the source image, yes. But what about the Y values in the video file? What analysis tool and methodology confirms 0, 16, 235, 255 are the Y values in the video file?

I’ve tried to replicate your findings. Since I don’t have your source image, I’m having to use my 0-16-235-255.png image. It should produce the same results.

Next, I run the command you posted for the limited range file:

ffmpeg -y -loop 1 -t 10 -i 0-16-235-255.png -pix_fmt yuv420p -c:v libx264 -vf scale=out_range=limited -color_primaries bt709 -color_trc bt709 -colorspace bt709 -r 59.94 -an Window_limited.mp4

Then I generate a digital waveform of that video:

ffmpeg -i Window_limited.mp4 -frames:v 1 -vf waveform=scale=digital:flags=numbers+dots:display=overlay:g=green:o=0.25 Window_limited_scope.png

Here is the waveform:

The stair steps are clearly at 16, 29, 217, 234. Those are the Y values.

Since the right-most swatch is only Y 234 according to the waveform, the above claim cannot be substantiated. The file doesn’t have a Y 255 value in it to check that IRE value. The highest value that’s been checked so far is Y 234.

The reason the highest value is Y 234 is because out_range=limited compressed the source image to 16-235, and now we have limited range data in a file flagged as limited range. In this state, we have a normal totally-regular limited range file where Y 235 is 100 IRE. Shotcut is correctly reporting IRE of the highest Y value in there, which is 234.

This file says nothing about the IRE of Y 255 without extrapolation. It doesn’t have a Y 255 in it. The waveform confirms it.

The correct value for this specific test case should be Y 255. I’m guessing you think it should be Y 235. But you haven’t said, so communication is unclear.

As described long ago, the Shotcut waveform is properly calculating IRE in all cases, and the video zoom is properly reporting Y values for all limited-range videos. None of your tests prove otherwise because you haven’t scoped a true Y 255 value yet.

It is impossible for the eyedropper to arrive at the correct value. Consider that Y 255 is a superwhite illegal value in a file flagged as limited range. Y 235 is supposed to be as white as it gets. An eyedropper cannot report a superwhite due to clipping during conversion. If the eyedropper agrees with an intentionally malformed, out of bounds, and illegally-valued limited range file, then that’s a clear sign the video file doesn’t actually have the right values in it.

I haven’t tried the ffplay scope or reviewed its source code. I only checked the waveform filter in ffmpeg. The proper description of ffmpeg’s problem is “IRE values are calculated using Y 235 on full-range video instead of Y 255”.

I’ve described that at least once today. Quintuple checked. Shotcut, VLC, eyedropper, videozoom, etc.

Have you checked the values in your .png image?

No, I explicitly said all values were correct and that means 255 = 255 with either a full or limited file in the Shotcut preview pane.

Yes I have. Eyedroppers and VLC and videozoom all report 255. They all work on my system. I’m thinking there is something in your system, such as a video codec or your .png images which is not giving you 255. They give me 255.

I’ll share my files and if they don’t show 255 on your system then definitely there is something wrong with your system, perhaps the codec. Heed what I said about the libav codec with its option to leave video levels untouched.

The file most definitely does have 255 but your system is not reproducing it. Frustrating, I know, but I’ve been bit in the ass on these issues in the past.

This is seriously off base. The eyedropper reads 255 on the R,G and B channels. Now perform the very simple weighted-sum calculation to arrive at Y. Because it’s designed to work with TV levels, when it encounters 255 it reads 108 IRE, which is correct. At 235 it reads 108 IRE. That is by design. It works this way for ANY image placed on the screen from any source.

https://libav.org/

Probably a typo , did you mean at RGB 235 it reads 100IRE ?

Can you check your file with ffplay, and measure your RGB values with a regular RGB eye dropper ?
2 tests

FFPlay -i input.mp4

FFPlay -i input.mp4 -vf scale=in_range=full

Remember , this check was done when we were tweaking your script. Remember, you went through a bunch of players, and none of them worked for the RGB check for EBU r103. You needed one that could enforce the conversion to the one you wanted. And some were slightly off, but for greyscale values it should be +/- 0 so you settled on FFPlay using full range

That 2nd one is your “unity” 0-255 YUV => 0-255 RGB . That’ s how you control the RGB conversion. You don’t need any math for greyscale values . Y = R,G,B in that case. If you have RGB 16, that corresponds to a Y value of 16

It’s just not possible to generate a value of Y=255 with that commandline. To be clear, I’m referring to the one Austin is referring to

`ffmpeg -y  -loop 1 -t 10  -i 0-16-235-255.png  -pix_fmt yuv420p  
-c:v libx264  -vf scale=out_range=limited  -color_primaries bt709  
-color_trc bt709  -colorspace bt709  -r 59.94  -an  Window_limited.mp4`

Maybe there was a mixup or typo somewhere. Unless there is some other weird issue with your input file . Was it a bmp or png ? PNG files can have a gAMA tag, which can sometimes mess things up .

Or upload your files

Yes, I meant 100 IRE. That’s what I get for typing with latex gloves on.

The script Austin uses has .png input files. My script has .bmp input files.

Already done. I’ve mentioned videozoom several times. I don’t know if you actually use Shotcut but it has something called “videozoom” which has an eyedropper. Would you be satisfied if I checked it with Gimp?

ffplay and VLC give the same levels, BTW.

Which commandline for ffplay, which version of VLC ?

Did you check Austin’s file ? Do you get the same results with his “FullValuesLimitedFlag.mp4” ?

Can you upload your files ?

I have already explained about VLC and why I reverted to an earlier version.

The ffplay command line specifies “full” when playing the full-range file and “limited” when playing the limited-range file.

Austin: did you check the levels on your png files?

I thought we are only interested in limited range one for this part

Can you report the RGB values with a “regular” color picker, when you play the limited range file for both

FFPlay -i input.mp4

FFPlay -i input.mp4 -vf scale=in_range=full

So if you used limited range, when playing the limited range file,
FFPlay -i input.mp4

and got the same display results in VLC, this implies VLC is using limited range

This means Y 16-235 => RGB 0-255

You should see RGB 0,0,0 and RGB 255,255,255 only . 2 patches, not 4.

That means the original values below Y=16, and above Y=235 were lost due to VLC

But this makes an assumption about the input file. I just want verification, and it’s easy to check with the file with other programs

Uploading the file would be preferrable


Austin’s video file file is ok “FullValuesLimitedFlag.mp4”, but his png file can produce different RGB values depending on the application used to view because of the metadata. For example, in Windows firefox , or photoshop, it look like RGB 0,15,234,255. When you run an application that ignores the tags it look like 0,16,235,255 .

It’s not really relevant in this case, because off by 1 is close enough, not sufficient explain the observations being reported. And what’s more important is the Y values are ok in his video. This is just more of an FYI but it’s more usually more of a problem the other way. You have some YUV video that has various tags, and you want to take a screenshot. FFmpeg does this for PNG files when the input file have various tags. The deviations can be much larger, when you have color, just something to be aware of PNG’s can be application dependent

Excellent! This should wrap up quickly then. Now that we know Shotcut’s video zoom is Y 255 (regardless of how the test file was built), we plug Y 255 into Shotcut source code and see what the IRE value is.

The line highlighted in the code below is basically inverting the Y value (0 → 255 and 255 → 0) to get X,Y coordinates on the waveform (as a graph) where 0,0 is the upper-left corner. So, running the scoped Y 255 through this function basically paints white on the top line of the IRE waveform (line 0 after inverting the Y 255 value), and the top line corresponds to IRE 108.

Thus, Y 255 is graphed as 108 IRE. This is the correct IRE. The result will not be system-dependent. I don’t see evidence of a Shotcut bug here.

What might be happening is that if the waveform isn’t given sufficient height on the screen in the Shotcut panel layout, then the top-most line will not be visible. It is easily crunched out by scaling if shrunk too small. The waveform has to be given a lot of real estate to accurately see everything.

Here’s an example where the waveform is sized quite small. IRE 108 is off the top of the graph and not visible:

WaveformSmall

Here’s an example where the waveform is given sufficient room to show everything:

To give credit where it’s due, Dan mentioned this as a possibility in his first post.

@pdr Thanks for the full independent review. Much appreciated. That takes system variability out of the equation.

For everyone’s satisfaction, I am attaching a second version using a BMP image source. The results are predictably the same.

FullValuesLimitedFlagBMP.zip (23.0 KB)

At this point, the issue seems resolved. If it isn’t, a screenshot of the faulty IRE waveform and a copy of the test video file would be needed for any conclusive analysis.

Here’s the source code for Shotcut’s waveform painter:

Very good work, Austin, and thanks for the validation. We need to make sure Brian sees this.

Is it feasible for Shotcut to examine the color-range flag and make 255 = 100 IRE if full range and 235 = 100 IRE if limited range? Is this how we want Shotcut to behave?

My pleasure. The nuance is that the Shotcut scopes never see the input files directly. The scopes only see the timeline output. The timeline is always limited range. So Y 235 will always be 100 IRE on the waveform.

If a full range video file is put on the timeline, Shotcut conforms (compresses) it to limited range before handing the data to the scopes. So the scopes never actually see data that’s flagged as full range.

So in essence, your recommendation is already happening. Y 255 in full range gets conformed to limited range Y 235 by the timeline, and Y 235 is handed over to the scope which in turn shows 100 IRE. By implicit conversion, Y 255 full range gets equated to 100 IRE which is correct.

Since the scopes only see conformed data via the timeline output, the only thing the scopes need to be designed for is limited range.

Do you mean have Brian change the drawing code so that 108 IRE is less likely to fall off the waveform if it’s drawn in a tiny window? Yes, that could be a benefit.

I just want to give some facts, both FFmpeg libavfilter waveform, vectorscope, histogram and others are used in professional environments and they are working just fine. Also features it have are unique in open source world. I wanted to even add more not yet implemented ScopeBox features later at same time. That also includes adding GPU variants of filters. Current ones are CPU only. About showing IRE at 100 for full range video case, I’m will do only what ScopeBox and what hardware scope would actually show.

Sure.

How is full-range video 0 - 255 being exported? Is it exported as 0 - 255 or 16 - 235? How about the preview pane? Is it seeing the “compressed” video range or full?

How do you account for the results I obtained in testing the ffplay scope?

I will check the flags in my files with ffprobe in addition to MediaInfo.

Depends on the export settings. As Dan mentioned in his second post, adding these three lines to the “Other” tab in advanced export will cause 0 - 255 output regardless of what the input format is (because input is always conformed to the format of the timeline, and the timeline is the only thing being exported):

mlt_image_format=rgb24
color_range=full
pix_fmt=yuvj420p

If those lines aren’t there, then the export will likely default to 16-235. It can depend on the codec being used of course, but you get the idea.

Preview is always limited range.

The “timeline format at time of export” is variable because it depends on the settings in the “Other” tab.

Regarding the videoZoom, I import a full-range video and the RGB values are reading correctly, for example, 234,234,234 (close enough), yet the Y value is reading 217. So the RGB values have not been compressed but the Y value has.

Yes, and the video is flagged as “full”, so bravo for that.