[FFmpeg-user] lutyuv filter clipping luma

Paulo Barretto pmbarretto at gmail.com
Thu Jun 26 15:29:12 CEST 2014

2014-06-15 11:43 GMT-03:00 Carl Eugen Hoyos <cehoyos at ag.or.at>:

> Indicating that your input files are broken or don't you agree?
> Use -color_range to force full range input, if you believe
> that there is a bug in FFmpeg, *please* provide a sample.

Sorry for my delayed answer, time has been short.
If you mean that format yuv420p should imply limited luma values, I do
believe you. But I am sure that the files are not corrupted, they are just
as recorded by the cameras. Maybe Sony and Panasonic don't follow encoding
I am not saying that there's a bug in FFmpeg, just reporting what I've

My problem, in few words, is:
I'm using libvpx codec to encode videos as webm. For all my yuv420p videos,
libvpx doesn't change color range, input and output histograms are
identical. But lutyuv filter, which seemed the most adequate for gamma
correction, clips output range.

I've done a lot of encoding tests with some video files, comparing the
input and different outputs with histogram filter. I've chosen videos with
strong highlights, so that luma histogram extension is easily seen.
Following is ffprobe output for the input files, and what I've observed.

D:\ffmpeg>bin\ffprobe P1010314.MOV
ffprobe version N-63861-g958168d Copyright (c) 2007-2014 the FFmpeg
  built on Jun  9 2014 22:02:00 with gcc 4.8.2 (GCC)
  configuration: --enable-gpl --enable-version3 --disable-w32threads
isynth --enable-bzlib --enable-fontconfig --enable-frei0r --enable-gnutls
le-iconv --enable-libass --enable-libbluray --enable-libcaca
e --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug
libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb
njpeg --enable-libopus --enable-librtmp --enable-libschroedinger
r --enable-libspeex --enable-libtheora --enable-libtwolame
--enable-libvidstab -
-enable-libvo-aacenc --enable-libvo-amrwbenc --enable-libvorbis
--enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265
libxavs --enable-libxvid --enable-decklink --enable-zlib
  libavutil      52. 89.100 / 52. 89.100
  libavcodec     55. 66.100 / 55. 66.100
  libavformat    55. 42.101 / 55. 42.101
  libavdevice    55. 13.101 / 55. 13.101
  libavfilter     4.  7.100 /  4.  7.100
  libswscale      2.  6.100 /  2.  6.100
  libswresample   0. 19.100 /  0. 19.100
  libpostproc    52.  3.100 / 52.  3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'P1010314.MOV':
    major_brand     : qt
    minor_version   : 537331972
    compatible_brands: qt  pana
    creation_time   : 2010-08-02 11:56:58
  Duration: 00:00:20.50, start: 0.000000, bitrate: 30965 kb/s
    Stream #0:0(eng): Video: mjpeg (jpeg / 0x6765706A), yuvj420p(pc),
30451 kb/s, 30 fps, 30 tbr, 30 tbn, 30 tbc (default)
      creation_time   : 2010-08-02 11:56:58
      encoder         : Photo - JPEG
    Stream #0:1(eng): Audio: pcm_s16be (twos / 0x736F7774), 16000 Hz, 2
, s16, 512 kb/s (default)
      creation_time   : 2010-08-02 11:56:58
D:\ffmpeg>bin\ffprobe -hide_banner MOV04461.MPG
Input #0, mpeg, from 'MOV04461.MPG':
  Duration: 00:00:28.47, start: 0.070000, bitrate: 10489 kb/s
    Stream #0:0[0x1c0]: Audio: mp2, 32000 Hz, mono, s16p, 64 kb/s
    Stream #0:1[0x1e0]: Video: mpeg1video, yuv420p(tv), 640x480 [SAR 1:1
DAR 4:3
], 104857 kb/s, 30 fps, 30 tbr, 90k tbn, 30 tbc
D:\ffmpeg>bin\ffprobe -hide_banner 00007.MTS
Input #0, mpegts, from '00007.MTS':
  Duration: 00:00:19.49, start: 0.366667, bitrate: 15097 kb/s
  Program 1
    Stream #0:0[0x1011]: Video: h264 (High) (HDMV / 0x564D4448),
yuv420p(tv), 12
80x720 [SAR 1:1 DAR 16:9], 59.94 fps, 29.97 tbr, 90k tbn, 119.88 tbc
    Stream #0:1[0x1100]: Audio: ac3 (AC-3 / 0x332D4341), 48000 Hz, stereo,
 192 kb/s
D:\ffmpeg>bin\ffprobe -hide_banner 00058.MTS
Input #0, mpegts, from '00058.MTS':
  Duration: 00:00:10.56, start: 0.752122, bitrate: 28080 kb/s
  Program 1
    Stream #0:0[0x1011]: Video: h264 (High) (HDPR / 0x52504448), yuv420p,
080 [SAR 1:1 DAR 16:9], 50 fps, 50 tbr, 90k tbn, 100 tbc
    Stream #0:1[0x1100]: Audio: ac3 (AC-3 / 0x332D4341), 48000 Hz, stereo,
 192 kb/s
    Stream #0:2[0x1200]: Subtitle: hdmv_pgs_subtitle ([144][0][0][0] /
D:\ffmpeg>bin\ffprobe -hide_banner P1210267.MP4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'P1210267.MP4':
    major_brand     : mp42
    minor_version   : 1
    compatible_brands: mp42avc1
    creation_time   : 2014-01-26 15:57:06
  Duration: 00:00:12.48, start: 0.000000, bitrate: 8514 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p,
[SAR 1:1 DAR 16:9], 7924 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc (default)
      creation_time   : 2014-01-26 15:57:06
    Stream #0:1(und): Audio: aac (mp4a / 0x6134706D), 48000 Hz, stereo,
fltp, 12
7 kb/s (default)
      creation_time   : 2014-01-26 15:57:06

The P1010314.MOV video is in fact yuvj420p, full range. Their output from
libvpx is clipped, or rather the histogram is "condensed" between the
clipping values (16-235 for luma, it seems). I've supposed this happens
when yuvj420p is converted to yuv420p for input to libvpx, and tried to use
"-vf scale=out_range=full". The clipping did not occur, and the histograms
for input and output files were identical.
The lutyuv filter, as Paul B. Mahol said, does not clip yuvj420p values.
Using "-vf lutyuv,scale=out_range=full" makes no change to histogram.

All other videos are yuv420p, but their luma histograms clearly extend to
full range.The histograms of the videos output from libvpx are identical to
the input ones.
But adding "-vf lutyuv" does clip them, and here it is really "clipping".
The output histogram is the same between the clipping values, and at these
two huge peaks gather all the values that were above or below them.

I've not found -color_range in ffmpeg documentation, but it seemed to me
that it should be used as an input option. After a lot of testing I found
out that using it like "-color_range 2 -i inputfile -vf
lutyuv,scale=out_range=full" could prevent the clipping, but only for
files P1210267.MP4 and 00058.MTS. For MOV04461.MPG and 00007.MTS it changed

I've made some more tests and found that:
- The hue filter does not clip any of the yuv420p videos. Using "-vf hue"
doesn't change the histogram, while "-vf hue=b=1" only shifts the luma
histogram, peaking values at 255.
- The geq filter also does not clip them. Using "-vf
geq=lum='p(X,Y)':cb='p(X,Y)'" doesn't change the histogram.

So, I'm using the geq filter for gamma correction of luma values, and all
yuv420p videos are being encoded by libvpx preserving full range.
The price to pay is much slower encoding. Expected, if instead of taken
from a lookup table, gamma correction is being calculated for each pixel of
each frame.

More information about the ffmpeg-user mailing list