<ol>
<li>yuvj420p is not obsolete, the ffmpeg message is just misleading</li>
<li>Compression errors? It doesn't really matter - all values less than 16 will be 16. Same with values over 235.</li>
</ol>

CC BY-SA 4.0
2022-07-03T16:32:41.000Z
As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer).
Community
CC BY-SA 4.0
2022-06-26T00:38:58.317Z
2022-06-26T00:38:58.317Z
rgr
<p>I'm searching for a reliable way to distinguish between the</p>
<ul>
<li><em>full-range (PC)</em> and</li>
<li><em>limited range (TV)</em></li>
</ul>
<p>pixel formats in a given video.</p>
<p>(Particularly, I will be satisfied with a solution for Y'UV 4:2:0 H.264 videos in the MP4 container.)</p>
<p>So my question is</p>
<p>     <strong>How to reliably determine whether a particular video is full-ranged or limited ranged?</strong></p>
<hr />
<p>Here is what I did to find a reliable way:
I created 3 testing videos with commands</p>
<pre><code>ffmpeg -f lavfi -i testsrc2=d=1                             test1.mp4
ffmpeg -f lavfi -i testsrc2=d=1 -vf scale=out_range=full    test2.mp4  
ffmpeg -f lavfi -i testsrc2=d=1 -vf scale=out_range=limited test3.mp4
</code></pre>
<p>which is the same as</p>
<pre><code>ffmpeg -f lavfi -i testsrc2=d=1                             test1.mp4
ffmpeg -f lavfi -i testsrc2=d=1 -vf scale=out_range=pc      test2.mp4  
ffmpeg -f lavfi -i testsrc2=d=1 -vf scale=out_range=tv      test3.mp4
</code></pre>
<p>They created these files:</p>
<blockquote>
<pre><code>test1.mp4  36,974 bytes
test2.mp4  40,178 bytes
test3.mp4  36,974 bytes
</code></pre>
</blockquote>
<p>where <code>test1.mp4</code> and <code>test3.mp4</code> have not only the same size, but they are <em>binary identical</em>, too.</p>
<p>While processing these commands, FFmpeg shows this message in the appropriate line of <code>Output #0</code> section (I show the message lines of these individual <code>ffmpeg</code> commands together, respectively, to see differences):</p>
<blockquote>
<pre><code>Stream #0:0: Video: h264 (avc1 / 0x31637661), yuv420p(progressive),     ... 
Stream #0:0: Video: h264 (avc1 / 0x31637661), yuv420p(pc, progressive), ...
Stream #0:0: Video: h264 (avc1 / 0x31637661), yuv420p(tv, progressive), ...
</code></pre>
</blockquote>
<p>Using <code>ffprobe</code> after creating videos, the appropriate lines (now from the <code>Input #0</code> section) will be</p>
<blockquote>
<pre><code>Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive),      ...
Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuvj420p(pc, progressive), ...
Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive),      ...
</code></pre>
</blockquote>
<p>Note changes in lines 2 and 3:</p>
<ul>
<li><p>pixel format for full range <em>changes</em> from <code>yuv420p</code> to <code>yuvj420p</code> (which is strange, because developers of FFmpeg themselves discourage using this pixel format as an <em>obsolete</em> one),</p>
</li>
<li><p>limited range is <em>not more mentioned</em> (no “tv” in parentheses).</p>
</li>
</ul>
<p>Now I will omit the <code>test1.mp4</code>, because it is the same as <code>test3.mp4</code>.</p>
<p>So I have 2 videos, <code>test2.mp4</code> with full-range and <code>test3.mp4</code> with limited range. The difference is visible (no such bright colors), as in these 2 screenshots placed one just below the other:</p>
<p><a href="https://i.sstatic.net/8cYzu.jpg" rel="nofollow noreferrer"><img src="https://i.sstatic.net/8cYzu.jpg" alt="enter image description here" /></a></p>
<p>The difference in the <code>ffprobe</code> output is in the pixel format, as I already demonstrated: <code>yuvj420p</code> vs. <code>yuv420p</code>.</p>
<p>But the <code>yuvj420p</code> is an obsolete pixel format, so if I want to tell if the video is full range, I probably can't rely on its occurrence in the <code>ffprobe</code> output as an indicator of the full-range video.</p>
<hr />
<p>I thank that a reliable way to distinguish between full-range and limited range is to <em>find values outside of limited range,</em> i.e.,</p>
<ul>
<li>outside of interval [16, 235] for the luma component (Y'), or</li>
<li>outside of interval [16, 240] for color components (U, V).</li>
</ul>
<p>So I used the <em>signalstats</em> filter as in this command</p>
<pre><code>ffprobe -f lavfi movie='test3.mp4',signalstats \
        -show_entries frame_tags=lavfi.signalstats.YMIN,lavfi.signalstats.YMAX
</code></pre>
<p>and filtered the output to see only outliers.</p>
<p>The <code>test2.mp4</code> video (full-ranged) gives me many of them:</p>
<blockquote>
<pre><code>TAG:lavfi.signalstats.YMIN=3
TAG:lavfi.signalstats.YMIN=6
TAG:lavfi.signalstats.YMIN=9
TAG:lavfi.signalstats.YMAX=237
TAG:lavfi.signalstats.YMIN=10
TAG:lavfi.signalstats.YMIN=10
TAG:lavfi.signalstats.YMIN=6
TAG:lavfi.signalstats.YMAX=240
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMIN=0
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMAX=237
TAG:lavfi.signalstats.YMIN=1
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMIN=5
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMIN=1
TAG:lavfi.signalstats.YMIN=4
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMAX=239
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMAX=239
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMAX=239
TAG:lavfi.signalstats.YMIN=4
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMAX=239
</code></pre>
</blockquote>
<p>But for my surprise, the <code>test3.mp4</code> video with <em>limited</em> range <strong>gives me outliers, too</strong>:</p>
<blockquote>
<pre><code>TAG:lavfi.signalstats.YMIN=11
TAG:lavfi.signalstats.YMIN=11
</code></pre>
</blockquote>
<p>So it is NOT a reliable way.</p>
<p>Let me repeat my question, accompanied by 2 secondary ones:</p>
<p>Main question:</p>
<ul>
<li><strong>How to reliably distinguish full-ranged and limited ranged videos?</strong></li>
</ul>
<p>Two tangential questions:</p>
<ul>
<li><p>Why a video, created <em>fully</em> with FFmpeg, has an <em>obsolete pixel format</em> <code>yuvj420p</code>, discouraged by FFmpeg developers?</p>
</li>
<li><p>Why in a <em>limited-range</em> video are still values <em>outside permitted range</em>?</p>
</li>
</ul>

<ffmpeg><ffprobe>
How to find out if the yuv420 video has full or limited color range?
MarianD
# How to find out if the yuv420 video has full or limited color range?

(Asked by: username_0 on 2022-01-30)

I'm searching for a reliable way to distinguish between the

full-range (PC) and
limited range (TV)

pixel formats in a given video.
(Particularly, I will be satisfied with a solution for Y'UV 4:2:0 H.264 videos in the MP4 container.)
So my question is
     How to reliably determine whether a particular video is full-ranged or limited ranged?

Here is what I did to find a reliable way:
I created 3 testing videos with commands
ffmpeg -f lavfi -i testsrc2=d=1                             test1.mp4
ffmpeg -f lavfi -i testsrc2=d=1 -vf scale=out_range=full    test2.mp4  
ffmpeg -f lavfi -i testsrc2=d=1 -vf scale=out_range=limited test3.mp4

which is the same as
ffmpeg -f lavfi -i testsrc2=d=1                             test1.mp4
ffmpeg -f lavfi -i testsrc2=d=1 -vf scale=out_range=pc      test2.mp4  
ffmpeg -f lavfi -i testsrc2=d=1 -vf scale=out_range=tv      test3.mp4

They created these files:

test1.mp4  36,974 bytes
test2.mp4  40,178 bytes
test3.mp4  36,974 bytes


where test1.mp4 and test3.mp4 have not only the same size, but they are binary identical, too.
While processing these commands, FFmpeg shows this message in the appropriate line of Output #0 section (I show the message lines of these individual ffmpeg commands together, respectively, to see differences):

Stream #0:0: Video: h264 (avc1 / 0x31637661), yuv420p(progressive),     ... 
Stream #0:0: Video: h264 (avc1 / 0x31637661), yuv420p(pc, progressive), ...
Stream #0:0: Video: h264 (avc1 / 0x31637661), yuv420p(tv, progressive), ...


Using ffprobe after creating videos, the appropriate lines (now from the Input #0 section) will be

Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive),      ...
Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuvj420p(pc, progressive), ...
Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive),      ...


Note changes in lines 2 and 3:

pixel format for full range changes from yuv420p to yuvj420p (which is strange, because developers of FFmpeg themselves discourage using this pixel format as an obsolete one),

limited range is not more mentioned (no “tv” in parentheses).


Now I will omit the test1.mp4, because it is the same as test3.mp4.
So I have 2 videos, test2.mp4 with full-range and test3.mp4 with limited range. The difference is visible (no such bright colors), as in these 2 screenshots placed one just below the other:

The difference in the ffprobe output is in the pixel format, as I already demonstrated: yuvj420p vs. yuv420p.
But the yuvj420p is an obsolete pixel format, so if I want to tell if the video is full range, I probably can't rely on its occurrence in the ffprobe output as an indicator of the full-range video.

I thank that a reliable way to distinguish between full-range and limited range is to find values outside of limited range, i.e.,

outside of interval [16, 235] for the luma component (Y'), or
outside of interval [16, 240] for color components (U, V).

So I used the signalstats filter as in this command
ffprobe -f lavfi movie='test3.mp4',signalstats \
        -show_entries frame_tags=lavfi.signalstats.YMIN,lavfi.signalstats.YMAX

and filtered the output to see only outliers.
The test2.mp4 video (full-ranged) gives me many of them:

TAG:lavfi.signalstats.YMIN=3
TAG:lavfi.signalstats.YMIN=6
TAG:lavfi.signalstats.YMIN=9
TAG:lavfi.signalstats.YMAX=237
TAG:lavfi.signalstats.YMIN=10
TAG:lavfi.signalstats.YMIN=10
TAG:lavfi.signalstats.YMIN=6
TAG:lavfi.signalstats.YMAX=240
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMIN=0
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMAX=237
TAG:lavfi.signalstats.YMIN=1
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMIN=5
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMIN=1
TAG:lavfi.signalstats.YMIN=4
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMAX=239
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMAX=239
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMAX=239
TAG:lavfi.signalstats.YMIN=4
TAG:lavfi.signalstats.YMIN=7
TAG:lavfi.signalstats.YMAX=239


But for my surprise, the test3.mp4 video with limited range gives me outliers, too:

TAG:lavfi.signalstats.YMIN=11
TAG:lavfi.signalstats.YMIN=11


So it is NOT a reliable way.
Let me repeat my question, accompanied by 2 secondary ones:
Main question:

How to reliably distinguish full-ranged and limited ranged videos?

Two tangential questions:

Why a video, created fully with FFmpeg, has an obsolete pixel format yuvj420p, discouraged by FFmpeg developers?

Why in a limited-range video are still values outside permitted range?

**Tags:** ffmpeg, ffprobe


---

## 1 answers

### Answer by username_1 on 2022-06-26. Score: -1

1. yuvj420p is not obsolete, the ffmpeg message is just misleading
2. Compression errors? It doesn't really matter - all values less than 16 will be 16. Same with values over 235.

> **Comments:**
> **username_2**: As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer).  

---

