ffmpeg Video Levels
|Reported by:||chris319||Owned by:|
|Blocking:||Reproduced by developer:||no|
|Analyzed by developer:||no|
This is a lengthy post.
I have been doing quite a bit of work with video levels and have some concerns regarding ffmpeg.
I have documented these concerns using a waveform monitor program. The x axis of the waveform monitor corresponds to the x axis of the image. The values on y axis under the "DIG" column represent all of the pixel intensities at a given x coordinate. The range is 0 - 255. Here is how the unaltered video of a Kodak Gray Card Plus appears. The video was taken with a Canon Vixia HF R800.
Note that there is no chrominance information in the right-hand 2/3 of the chart. I use a C-language program to read a single frame of video from the mp4 file and place the samples into an array. The C program creates input and output pipes to ffmpeg which is used to read and write a frame of video. Here is the code used to read a frame of video into ffmpeg, showing the command line ffmpeg receives:
FILE *pipein = popen("ffmpeg -i KodakChart.mp4 -f image2pipe -vcodec rawvideo -pix_fmt yuv420p -", "r");
Here is the code used to write a video frame to ffmpeg, also showing the ffmpeg command line:
FILE *pipeout = popen("ffmpeg -y -f rawvideo -vcodec rawvideo -pix_fmt yuv420p -s 1280x720 -r 29.97 -i - -f mp4 -q:v 5 -vf scale=out_range=tv cliptest.mp4", "w");
Once the YUV samples are in the array, I use the C code below to force the luminance component of all pixels to a specific value. In the example below, 235 is chosen, as this is the maximum video level specified in ITU BT.709.
for (y=0; y<H ; y++)
for (x=0; x<W ; x++)
lum[y*W+x] = 235;
Below are several waveform shots of video levels at various vales.
In the first waveform shot, all luminance components have been forced to digital 255.
Here is a waveform shot with all luminance components forced to digital 110.
Below, all luminance components forced to digital 180. As we can see, the video levels are actually slightly higher than 180.
In the next scope display, all luminance components have been forced to digital 235.
This scope display is especially noteworthy because the video levels reach 255 despite having been forced to 235.
It is possible to force the luminance component to a specific value by reading and writing a frame of video using ffmpeg. The example which shows luma forced to 110 works fairly well. As we increase the video level, ffmpeg is applying gain to the levels. Finally, when luma is forced to 235, ffmpeg is boosting the levels to 255. Note that the code for the output pipe contains the following video filter:
It appears that this filter is not functioning as documented, i.e. it is not confining the output to the range of 16 - 235. This could be problematic if a user needs 16 - 235 output. For example, the U.S. broadcast TV station I work for would never broadcast any of the examples shown in this post having video levels above digital 235.
Change History (9)
comment:1 by , 4 years ago
|Component:||avcodec → undetermined|