Changes between Version 5 and Version 6 of colorspace
- Timestamp:
- Jun 7, 2019, 9:36:45 PM (22 months ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
colorspace
v5 v6 1 1 = Colorspace support in FFmpeg = 2 2 3 == What is colorspace? ==4 5 Colorspace describes how pixel values are stored within a file or displayed on the screen, and what the range and meaning of those values are. 6 7 For example, it describes how the values of pixels store color information (e.g. RGB or YUV), and how the values of each color component (e.g., R, G, or B) should be translated in order to be properly displayed by the screen. 8 9 The difference between RGB and YUV is, in simple terms: 10 11 - RGB distinguishes color in three components: Red, Green, Blue 12 - YUV represents color in brightness (Y) and color differences (UV).13 3 == What is colorspace? Why should we care? == 4 Colorspace describes how an array of pixel values should be displayed on the screen. It provides information like how pixel values are stored within a file, and what the range and meaning of those values are. 5 6 Basically, it tells the format of the array of pixels (e.g. RGB or YUV), and how the values of each color component should be translated, to be properly displayed by the photons of the screen. (i.e. picking a colorspace randomly seems unlikely a good choice...) 7 [[BR]] 8 [[BR]] 9 [[BR]] 10 The difference between RGB and YUV should be rather obvious: 11 12 - RGB distinguishes color pixel values into 3 components: Red, Green, Blue. (hence the name) 13 - YUV uses a different representation schema that represents color pixel values in: Luminance (Y, or brightness), Chroma (UV, or color differences). ^(Note: YUV represents color in 3 components)^ 14 14 {{{ 15 15 #!div style="border: 1px solid #e5e5c7; margin: 1em; background-color: #ffd;" 16 16 '''Note:''' The term "YUV" is ambiguous and often used wrongly, including the definition of pixel formats in FFmpeg. A more accurate term for how color is stored in digital video would be [https://en.wikipedia.org/wiki/YCbCr YCbCr]. Y'UV on other other hand specifies a colorspace consisting of luma (Y') and chrominance (UV) components. For more info read [https://en.wikipedia.org/wiki/YUV the respective Wikipedia article]. In the following, the term YUV is used as in the FFmpeg pixel formats, referring to YCbCr in digital video. 17 17 }}} 18 18 [[BR]] 19 [[BR]] 19 20 The conversion between YUV pixel buffer representation and its visual representation depends on the type of the YUV represented in the pixel buffers, which are essentially device-dependent. 20 21 … … 24 25 - [https://en.wikipedia.org/wiki/Rec._2020 BT.2020] ("Ultra-High-Definition" or UHD) 25 26 26 These standards describe not just converions froma YUV signal to RGB, but also how a RGB signal should be represented in terms of photon emission, in a device-independent way.27 These standards describe not just things like how to convert a YUV signal to RGB, but also how a RGB signal should be represented in terms of photon emission, in a device-independent way. 27 28 28 29 == How does FFmpeg identify colorspaces? == 29 30 30 In FFmpeg, colorspace is represented in [http://git.videolan.org/?p=ffmpeg.git;a=blob;f=libavutil/pixfmt.h;hb=HEAD pixel formats]. 31 32 In practical terms, the things you care about are: 33 34 1. Whether the pixel buffer contains RGB, YUV or some other type of pixel format, and the bit-depth. 35 2. Whether the signals are full range or restricted range. (YUV only, unlikely a problem for other type of signals...) 31 In FFmpeg, colorspaces are represented in the form of [http://git.videolan.org/?p=ffmpeg.git;a=blob;f=libavutil/pixfmt.h;hb=HEAD pixel format]. 32 [[BR]] 33 [[BR]] 34 In practical terms, the things you care are: 35 36 1. Whether the pixel buffer contains RGB, YUV or some other type of signals, and the bit-depth. 37 2. Whether the signals are full range or restricted range. (YUV only, unlikely a problem for other type of signals...) ^(Note: "Full range" refers to the YUV component values being in the range 0–255, whereas "restricted range" has values between 16–235)^ 36 38 3. The transformation matrix between YUV and RGB. 37 39 4. The linearization function from RGB to a linear RGB signal. 38 40 5. The conversion matrix between the linearized RGB and the device-independent XYZ colorspace. 39 40 "Full range" refers to the YUV component values being in the range 0–255, whereas "restricted range" has values between 16–235. 41 41 [[BR]] 42 42 FFmpeg stores all these properties in the [https://ffmpeg.org/doxygen/trunk/structAVFrame.html AVFrame] struct: 43 43 … … 45 45 - The signal range, in AVFrame->[https://ffmpeg.org/doxygen/trunk/structAVFrame.html#a853afbad220bbc58549b4860732a3aa5 color_range] 46 46 - The YUV/RGB transformation matrix, in AVFrame->[https://ffmpeg.org/doxygen/trunk/structAVFrame.html#a9262c231f1f64869439b4fe587fe1710 colorspace] 47 - The linearization function (a ka. transformation characteristics), in AVFrame->[https://ffmpeg.org/doxygen/trunk/structAVFrame.html#ab09abb126e3922bc1d010cf044087939 color_trc]47 - The linearization function (a.k.a. transformation characteristics), in AVFrame->[https://ffmpeg.org/doxygen/trunk/structAVFrame.html#ab09abb126e3922bc1d010cf044087939 color_trc] 48 48 - The RGB/XYZ matrix, in AVFrame->[https://ffmpeg.org/doxygen/trunk/structAVFrame.html#a59a3f830494f2ed1133103a1bc9481e7 color_primaries] 49 49 … … 51 51 52 52 Conversion between RGB/YUV is typically done using swscale. Conversion between different color properties (bit-depth, range, matrix, transfer characteristics, primaries) can be done using the [https://ffmpeg.org/ffmpeg-filters.html#colorspace colorspace] or [https://ffmpeg.org/ffmpeg-filters.html#colormatrix colormatrix] video filter. There's also a filter using the external library [https://ffmpeg.org/ffmpeg-filters.html#zscale zscale]. (for both aforementioned purposes) ^(...and seems to be a more reliable choice for all these swscale hazards)^ 53 53 [[BR]] 54 [[BR]] 55 [[BR]] 54 56 Video filter `colorspace`, `colormatrix` have the following relationship: 55 57 … … 57 59 - `colormatrix` supports only 8bpc (8-bit per component) pixel formats, whereas `colorspace` supports 10bpc, 12bpc also. 58 60 - `colormatrix` does not apply gamma (primaries) correction, whereas `colorspace` does (it has an option `fast=1` to disable this if you want faster conversion, or compatible output with that produced by `colormatrix`). ^(Note: With `fast=0` (default) it seems to produce significantly worse quality (discoloration)... gamma miscorrection?..)^ 59 - `colormatrix` is C only, whereas `colorspace` uses x86 SIMD (ie. it's faster). 60 61 The major difference between them is `colormatrix` produces horrible quality for anything > 8bpc (8-bit per component)... while `colorspace` produces something decent, at least for 10bpc (for 8bpc they both produce similar bad quality... probably due to improper design in the algorithms). ^(floor instead of round on color approximation?..)^[[BR]] 62 63 For 8bpc, `colorspace` still seems to produce slightly better quality than `colormatrix` (while it's pointless... as doing things in 10bpc first, then 10bpc -> 8bpc seems to be a better approach... if you don't mind dithering). ^([https://trac.ffmpeg.org/ticket/4614 dithering is enforced in swscale YUV 10bpc -> 8bpc])^ 64 61 - `colormatrix` is C only, whereas `colorspace` uses x86 SIMD (i.e. it's faster). 62 [[BR]] 63 Anyway the major difference between them is `colormatrix` produces horrible quality for anything > 8bpc (8-bit per component)... while `colorspace` produces something decent, at least for 10bpc (for 8bpc they both produce similar bad quality... probably due to improper design in the algorithms). ^(floor instead of round on color approximation?..)^[[BR]] 64 Anyway for 8bpc... `colorspace` still seems to produce slightly better quality than `colormatrix` (while it's pointless... as doing things in 10bpc first, then 10bpc -> 8bpc seems to be a better approach... if you don't mind dithering). ^([https://trac.ffmpeg.org/ticket/4614 dithering is enforced in swscale YUV 10bpc -> 8bpc])^ 65 [[BR]] 66 [[BR]] 67 [[BR]] 68 [[BR]] 69 [[BR]] 65 70 Read the filters' respective documentation to read up exactly on how to use them. 66 71 67 72 The easiest way to use these filters is to ensure that the input AVFrames have all relevant struct members set to the appropriate value. (or got to specify them manually as the filter arguments...)[[BR]] 68 73 Then, set the target color properties on the video filter, and it will output the converted frames. 69 74 [[BR]] 75 [[BR]] 76 [[BR]] 70 77 To convert RGB/YUV or scale using swscale, use swscale and set the appropriate color properties using [https://ffmpeg.org/doxygen/trunk/group__lsws.html#ga541bdffa8149f5f9203664f955faa040 sws_setColorspaceDetails](). 71 78 72 == Examples ==73 74 These use a [https://zeranoe.com/builds/win64/static/ffmpeg-20190416-e2f766e-win64-static.zip build from Zeranoe].75 76 Caveat: For all these images to be properly displayed, a decent browser is a requisite. 77 79 == Examples ^(Build from: https://zeranoe.com/builds/win64/static/ffmpeg-20190416-e2f766e-win64-static.zip)^ == 80 81 Caveat: For all these images to be properly displayed... some decent browser shall be a requisite. 82 [[BR]] 83 [[BR]] 84 [[BR]] 78 85 ==== The input source (rgb24): ==== 79 86 80 87 [[Image(https://trac.ffmpeg.org/raw-attachment/wiki/colorspace/origin(rgb24).png, 720px)]] 81 88 [[BR]] 89 [[BR]] 90 [[BR]] 91 [[BR]] 92 [[BR]] 93 [[BR]] 94 [[BR]] 82 95 ==== `colormatrix` (yuv444p10le): ==== 83 84 96 {{{ 85 97 ffmpeg -i "origin(rgb24).png" -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" -pix_fmt yuv444p10le -sws_flags spline+accurate_rnd+full_chroma_int -vf "colormatrix=bt470bg:bt709" -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 "colormatrix_yuv444p10le.avi" 86 98 ffmpeg -i "colormatrix_yuv444p10le.avi" -compression_level 10 -pred mixed -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int "colormatrix_yuv444p10le.png" 87 99 }}} 88 89 100 Output bit-identical as [#colormatrixyuv444p: `colormatrix` (yuv444p)]. 90 101 [[BR]] 102 [[BR]] 91 103 ==== `colorspace` (yuv444p10le): ^(Note: SSIM > 99.98% with [#Theinputsourcergb24: The input source (rgb24)]. Should be 100% if the conversion algorithms are improved though...)^ ==== 92 93 104 {{{ 94 105 ffmpeg -i "origin(rgb24).png" -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" -pix_fmt yuv444p10le -sws_flags spline+accurate_rnd+full_chroma_int -vf "colorspace=bt709:iall=bt601-6-625:fast=1" -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 "colorspace_yuv444p10le.avi" 95 106 ffmpeg -i "colorspace_yuv444p10le.avi" -compression_level 10 -pred mixed -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int "colorspace_yuv444p10le.png" 96 107 }}} 97 98 108 [[Image(https://trac.ffmpeg.org/raw-attachment/wiki/colorspace/colorspace_yuv444p10le.png, 720px)]] 99 109 [[BR]] 110 [[BR]] 111 [[BR]] 112 [[BR]] 113 [[BR]] 100 114 ==== Reference (yuv444p): ==== 101 102 115 {{{ 103 116 ffmpeg -i "origin(rgb24).png" -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" -pix_fmt yuv444p -sws_flags spline+accurate_rnd+full_chroma_int -color_range 1 -colorspace 5 -color_primaries 5 -color_trc 6 "yuv444p.avi" 104 117 ffmpeg -i "yuv444p.avi" -compression_level 10 -pred mixed -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int "yuv444p.png" 105 118 }}} 106 107 119 [[Image(https://trac.ffmpeg.org/raw-attachment/wiki/colorspace/yuv444p.png, 720px)]] 108 120 [[BR]] 121 [[BR]] 109 122 ==== `colormatrix` (yuv444p): ==== 110 111 123 {{{ 112 124 ffmpeg -i "origin(rgb24).png" -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" -pix_fmt yuv444p -sws_flags spline+accurate_rnd+full_chroma_int -vf "colormatrix=bt470bg:bt709" -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 "colormatrix_yuv444p.avi" 113 125 ffmpeg -i "colormatrix_yuv444p.avi" -compression_level 10 -pred mixed -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int "colormatrix_yuv444p.png" 114 126 }}} 115 116 127 [[Image(https://trac.ffmpeg.org/raw-attachment/wiki/colorspace/colormatrix_yuv444p.png, 720px)]] 117 128 [[BR]] 129 [[BR]] 118 130 ==== `colorspace` (yuv444p): ==== 119 120 131 {{{ 121 132 ffmpeg -i "origin(rgb24).png" -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" -pix_fmt yuv444p -sws_flags spline+accurate_rnd+full_chroma_int -vf "colorspace=bt709:iall=bt601-6-625:fast=1" -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 "colorspace_yuv444p.avi" 122 133 ffmpeg -i "colorspace_yuv444p.avi" -compression_level 10 -pred mixed -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int "colorspace_yuv444p.png" 123 134 }}} 124 125 135 [[Image(https://trac.ffmpeg.org/raw-attachment/wiki/colorspace/colorspace_yuv444p.png, 720px)]] 126 136 [[BR]] 137 [[BR]] 127 138 ==== `colorspace` (yuv444p10le -> yuv444p): ==== 128 129 139 {{{ 130 140 ffmpeg -i "colorspace_yuv444p10le.avi" -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" -pix_fmt yuv444p -sws_flags spline+accurate_rnd+full_chroma_int -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 "colorspace_yuv444p10le-yuv444p.avi" 131 141 ffmpeg -i "colorspace_yuv444p10le-yuv444p.avi" -compression_level 10 -pred mixed -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int "colorspace_yuv444p10le-yuv444p.png" 132 142 }}} 133 134 143 [[Image(https://trac.ffmpeg.org/raw-attachment/wiki/colorspace/colorspace_yuv444p10le-yuv444p.png, 720px)]] 135 144 [[BR]] 145 [[BR]] 146 [[BR]] 147 [[BR]] 148 [[BR]] 149 [[BR]] 150 [[BR]] 136 151 ==== `colorspace` with `fast=0` `iall=bt601-6-625`: ==== 137 138 152 {{{ 139 153 ffmpeg -i "origin(rgb24).png" -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" -pix_fmt yuv444p10le -sws_flags spline+accurate_rnd+full_chroma_int -vf "colorspace=bt709:iall=bt601-6-625" -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 "colorspace_fast=0_iall=bt601-6-625.avi" 140 154 ffmpeg -i "colorspace_fast=0_iall=bt601-6-625.avi" -compression_level 10 -pred mixed -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int "colorspace_fast=0_iall=bt601-6-625.png" 141 155 }}} 142 143 156 [[Image(https://trac.ffmpeg.org/raw-attachment/wiki/colorspace/colorspace_fast%3D0_iall%3Dbt601-6-625.png, 720px)]] 144 157 [[BR]] 158 [[BR]] 145 159 ==== `colorspace` with `fast=0` `iall=bt601-6-525`: ==== 146 147 160 {{{ 148 161 ffmpeg -i "origin(rgb24).png" -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" -pix_fmt yuv444p10le -sws_flags spline+accurate_rnd+full_chroma_int -vf "colorspace=bt709:iall=bt601-6-525" -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 "colorspace_fast=0_iall=bt601-6-525.avi" 149 162 ffmpeg -i "colorspace_fast=0_iall=bt601-6-525.avi" -compression_level 10 -pred mixed -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int "colorspace_fast=0_iall=bt601-6-525.png" 150 163 }}} 151 152 164 [[Image(https://trac.ffmpeg.org/raw-attachment/wiki/colorspace/colorspace_fast%3D0_iall%3Dbt601-6-525.png, 720px)]] 153 165 [[BR]] 166 [[BR]] 154 167 ==== `colorspace` with `fast=1` `iall=bt601-6-525`: ==== 155 156 168 {{{ 157 169 ffmpeg -i "origin(rgb24).png" -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" -pix_fmt yuv444p10le -sws_flags spline+accurate_rnd+full_chroma_int -vf "colorspace=bt709:iall=bt601-6-525:fast=1" -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 "colorspace_fast=1_iall=bt601-6-525.avi" 158 170 ffmpeg -i "colorspace_fast=1_iall=bt601-6-525.avi" -compression_level 10 -pred mixed -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int "colorspace_fast=1_iall=bt601-6-525.png" 159 171 }}} 160 161 172 Output bit-identical as [#colorspaceyuv444p10le:Note:SSIM99.98withTheinputsourcergb24.Shouldbe100iftheconversionalgorithmsareimprovedthough... `colorspace` (yuv444p10le)]. 162 173 [[BR]] 174 [[BR]] 175 [[BR]] 176 [[BR]] 177 [[BR]] 178 [[BR]] 179 [[BR]] 163 180 ==== Reference (yuv420p10le): ==== 164 165 181 {{{ 166 182 ffmpeg -i "origin(rgb24).png" -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" -pix_fmt yuv420p10le -sws_flags spline+accurate_rnd+full_chroma_int -color_range 1 -colorspace 5 -color_primaries 5 -color_trc 6 "yuv420p10le.avi" 167 183 ffmpeg -i "yuv420p10le.avi" -compression_level 10 -pred mixed -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int "yuv420p10le.png" 168 184 }}} 169 170 185 [[Image(https://trac.ffmpeg.org/raw-attachment/wiki/colorspace/yuv420p10le.png, 720px)]] 171 186 [[BR]] 187 [[BR]] 172 188 ==== `colorspace` (yuv420p10le): ==== 173 174 189 {{{ 175 190 ffmpeg -i "origin(rgb24).png" -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" -pix_fmt yuv420p10le -sws_flags spline+accurate_rnd+full_chroma_int -vf "colorspace=bt709:iall=bt601-6-625:fast=1" -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 "colorspace_yuv420p10le.avi" 176 191 ffmpeg -i "colorspace_yuv420p10le.avi" -compression_level 10 -pred mixed -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int "colorspace_yuv420p10le.png" 177 192 }}} 178 179 193 [[Image(https://trac.ffmpeg.org/raw-attachment/wiki/colorspace/colorspace_yuv420p10le.png, 720px)]] 180 194 [[BR]] 195 [[BR]] 196 [[BR]] 197 [[BR]] 198 [[BR]] 181 199 ==== Reference (yuv420p): ==== 182 183 200 {{{ 184 201 ffmpeg -i "origin(rgb24).png" -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" -pix_fmt yuv420p -sws_flags spline+accurate_rnd+full_chroma_int -color_range 1 -colorspace 5 -color_primaries 5 -color_trc 6 "yuv420p.avi" 185 202 ffmpeg -i "yuv420p.avi" -compression_level 10 -pred mixed -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int "yuv420p.png" 186 203 }}} 187 188 204 [[Image(https://trac.ffmpeg.org/raw-attachment/wiki/colorspace/yuv420p.png, 720px)]] 189 190 205 [[BR]] 206 [[BR]] 191 207 ==== `colorspace` (yuv420p): ==== 192 193 208 {{{ 194 209 ffmpeg -i "origin(rgb24).png" -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" -pix_fmt yuv420p -sws_flags spline+accurate_rnd+full_chroma_int -vf "colorspace=bt709:iall=bt601-6-625:fast=1" -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 "colorspace_yuv420p.avi" 195 210 ffmpeg -i "colorspace_yuv420p.avi" -compression_level 10 -pred mixed -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int "colorspace_yuv420p.png" 196 211 }}} 197 198 212 [[Image(https://trac.ffmpeg.org/raw-attachment/wiki/colorspace/colorspace_yuv420p.png, 720px)]] 199 213 [[BR]] 214 [[BR]] 200 215 ==== `colorspace` (yuv420p10le -> yuv420p): ==== 201 202 216 {{{ 203 217 ffmpeg -i "colorspace_yuv420p10le.avi" -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" -pix_fmt yuv420p -sws_flags spline+accurate_rnd+full_chroma_int -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 "colorspace_yuv420p10le-yuv420p.avi" 204 218 ffmpeg -i "colorspace_yuv420p10le-yuv420p.avi" -compression_level 10 -pred mixed -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int "colorspace_yuv420p10le-yuv420p.png" 205 219 }}} 206 207 220 [[Image(https://trac.ffmpeg.org/raw-attachment/wiki/colorspace/colorspace_yuv420p10le-yuv420p.png, 720px)]] 208 221 [[BR]] 222 [[BR]] 209 223 ==== `colorspace` (yuv444p10le -> yuv420p): ==== 210 211 224 {{{ 212 225 ffmpeg -i "colorspace_yuv444p10le.avi" -c:v libx264 -preset placebo -qp 0 -x264-params "keyint=15:no-deblock=1" -pix_fmt yuv420p -sws_flags spline+accurate_rnd+full_chroma_int -color_range 1 -colorspace 1 -color_primaries 1 -color_trc 1 "colorspace_yuv444p10le-yuv420p.avi" 213 226 ffmpeg -i "colorspace_yuv444p10le-yuv420p.avi" -compression_level 10 -pred mixed -pix_fmt rgb24 -sws_flags +accurate_rnd+full_chroma_int "colorspace_yuv444p10le-yuv420p.png" 214 227 }}} 215 216 228 [[Image(https://trac.ffmpeg.org/raw-attachment/wiki/colorspace/colorspace_yuv444p10le-yuv420p.png, 720px)]]