]> git.sesse.net Git - movit/blob - ycbcr.h
Add input support for packed 10-bit Y'CbCr.
[movit] / ycbcr.h
1 #ifndef _MOVIT_YCBCR_H
2 #define _MOVIT_YCBCR_H 1
3
4 // Shared utility functions between YCbCrInput, YCbCr422InterleavedInput
5 // and YCbCrConversionEffect.
6 //
7 // Conversion from integer to floating-point representation in case of
8 // Y'CbCr is seemingly tricky:
9 //
10 // BT.601 page 8 has a table that says that for luma, black is at 16.00_d and
11 // white is at 235.00_d. _d seemingly means “on a floating-point scale from 0
12 // to 255.75”, see §2.4. The .75 is because BT.601 wants to support 10-bit,
13 // but all values are scaled for 8-bit since that's the most common; it is
14 // specified that conversion from 8-bit to 10-bit is done by inserting two
15 // binary zeroes at the end (not repeating bits as one would often do
16 // otherwise). It would seem that BT.601 lives in a world where the idealized
17 // range is really [0,256), not [0,255].
18 //
19 // However, GPUs (and by extension Movit) don't work this way. For them,
20 // typically 1.0 maps to the largest possible representable value in the
21 // framebuffer, ie., the range [0.0,1.0] maps to [0,255] for 8-bit
22 // and to [0,1023] (or [0_d,255.75_d] in BT.601 parlance) for 10-bit.
23 //
24 // BT.701 (page 5) seems to agree with BT.601; it specifies range 16–235 for
25 // 8-bit luma, and 64–940 for 10-bit luma. This would indicate, for a GPU,
26 // that that for 8-bit mode, the range would be 16/255 to 235/255
27 // (0.06275 to 0.92157), while for 10-bit, it should be 64/1023 to 940/1023
28 // (0.06256 to 0.91887). There's no good compromise here; if you select 8-bit
29 // range, 10-bit goes out of range (white gets to 942), while if you select
30 // 10-bit range, 8-bit gets only to 234, making true white impossible.
31 //
32 // Thus, you will need to specify the actual precision of the Y'CbCr source
33 // (or destination); the num_levels field is the right place. Most people
34 // will want to simply set this to 256, as 8-bit Y'CbCr is the most common,
35 // but the right value will naturally depend on your input.
36
37 #include "image_format.h"
38
39 #include <Eigen/Core>
40
41 namespace movit {
42
43 struct YCbCrFormat {
44         // Which formula for Y' to use.
45         YCbCrLumaCoefficients luma_coefficients;
46
47         // If true, assume Y'CbCr coefficients are full-range, ie. go from 0 to 255
48         // instead of the limited 220/225 steps in classic MPEG. For instance,
49         // JPEG uses the Rec. 601 luma coefficients, but full range.
50         bool full_range;
51
52         // Set to 2^n for n-bit Y'CbCr (e.g. 256 for 8-bit Y'CbCr).
53         // See file-level comment.
54         int num_levels;
55
56         // Sampling factors for chroma components. For no subsampling (4:4:4),
57         // set both to 1.
58         unsigned chroma_subsampling_x, chroma_subsampling_y;
59
60         // Positioning of the chroma samples. MPEG-1 and JPEG is (0.5, 0.5);
61         // MPEG-2 and newer typically are (0.0, 0.5).
62         float cb_x_position, cb_y_position;
63         float cr_x_position, cr_y_position;
64 };
65
66 // Convert texel sampling offset for the given chroma channel, given that
67 // chroma position is <pos> (0..1), we are downsampling this chroma channel
68 // by a factor of <subsampling_factor> and the texture we are sampling from
69 // is <resolution> pixels wide/high.
70 float compute_chroma_offset(float pos, unsigned subsampling_factor, unsigned resolution);
71
72 // Given <ycbcr_format>, compute the values needed to turn Y'CbCr into R'G'B';
73 // first subtract the returned offset, then left-multiply the returned matrix
74 // (the scaling is already folded into it).
75 void compute_ycbcr_matrix(YCbCrFormat ycbcr_format, float *offset, Eigen::Matrix3d *ycbcr_to_rgb);
76
77 }  // namespace movit
78
79 #endif // !defined(_MOVIT_YCBCR_INPUT_H)