]> git.sesse.net Git - movit/blob - ycbcr_422interleaved_input_test.cpp
d47bb905cb43e466350204cf69d775172134bb74
[movit] / ycbcr_422interleaved_input_test.cpp
1 // Unit tests for YCbCr422InterleavedInput.
2
3 #include <epoxy/gl.h>
4 #include <stddef.h>
5
6 #include "effect_chain.h"
7 #include "gtest/gtest.h"
8 #include "test_util.h"
9 #include "util.h"
10 #include "ycbcr_422interleaved_input.h"
11
12 namespace movit {
13
14 // Adapted from the Simple444 test from YCbCrInputTest.
15 TEST(YCbCr422InterleavedInputTest, Simple422) {
16         const int width = 2;
17         const int height = 5;
18
19         // Pure-color test inputs, calculated with the formulas in Rec. 601
20         // section 2.5.4.
21         unsigned char uyvy[width * height * 2] = {
22                 /*U=*/128, /*Y=*/ 16, /*V=*/128, /*Y=*/ 16,
23                 /*U=*/128, /*Y=*/235, /*V=*/128, /*Y=*/235,
24                 /*U=*/ 90, /*Y=*/ 81, /*V=*/240, /*Y=*/ 81,
25                 /*U=*/ 54, /*Y=*/145, /*V=*/ 34, /*Y=*/145,
26                 /*U=*/240, /*Y=*/ 41, /*V=*/110, /*Y=*/ 41,
27         };
28
29         float expected_data[4 * width * height] = {
30                 0.0, 0.0, 0.0, 1.0,   0.0, 0.0, 0.0, 1.0,
31                 1.0, 1.0, 1.0, 1.0,   1.0, 1.0, 1.0, 1.0,
32                 1.0, 0.0, 0.0, 1.0,   1.0, 0.0, 0.0, 1.0,
33                 0.0, 1.0, 0.0, 1.0,   0.0, 1.0, 0.0, 1.0,
34                 0.0, 0.0, 1.0, 1.0,   0.0, 0.0, 1.0, 1.0,
35         };
36         float out_data[4 * width * height];
37
38         EffectChainTester tester(NULL, width, height);
39
40         ImageFormat format;
41         format.color_space = COLORSPACE_sRGB;
42         format.gamma_curve = GAMMA_sRGB;
43
44         YCbCrFormat ycbcr_format;
45         ycbcr_format.luma_coefficients = YCBCR_REC_601;
46         ycbcr_format.full_range = false;
47         ycbcr_format.chroma_subsampling_x = 2;
48         ycbcr_format.chroma_subsampling_y = 1;
49         ycbcr_format.cb_x_position = 0.0f;  // Doesn't really matter here, since Y is constant.
50         ycbcr_format.cb_y_position = 0.5f;
51         ycbcr_format.cr_x_position = 0.0f;
52         ycbcr_format.cr_y_position = 0.5f;
53
54         YCbCr422InterleavedInput *input = new YCbCr422InterleavedInput(format, ycbcr_format, width, height);
55         input->set_pixel_data(uyvy);
56         tester.get_chain()->add_input(input);
57
58         tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_sRGB);
59
60         // Y'CbCr isn't 100% accurate (the input values are rounded),
61         // so we need some leeway.
62         expect_equal(expected_data, out_data, 4 * width, height, 0.025, 0.002);
63 }
64
65 // Adapted from the YCbCrInput test of the same name.
66 TEST(YCbCr422InterleavedInputTest, DifferentCbAndCrPositioning) {
67         const int width = 4;
68         const int height = 4;
69
70         unsigned char uyvy[width * height * 2] = {
71                 /*U=*/ 64, /*Y=*/126, /*V=*/ 48, /*Y=*/126,  /*U=*/128, /*Y=*/126, /*V=*/128, /*Y=*/126,
72                 /*U=*/128, /*Y=*/126, /*V=*/128, /*Y=*/126,  /*U=*/192, /*Y=*/126, /*V=*/208, /*Y=*/126,
73                 /*U=*/128, /*Y=*/126, /*V=*/128, /*Y=*/126,  /*U=*/128, /*Y=*/126, /*V=*/128, /*Y=*/126,
74                 /*U=*/128, /*Y=*/126, /*V=*/128, /*Y=*/126,  /*U=*/128, /*Y=*/126, /*V=*/128, /*Y=*/126,
75         };
76
77         // Chroma samples in this case are always co-sited with a luma sample;
78         // their associated color values and position are marked off in comments.
79         float expected_data_blue[width * height] = {
80                    0.000 /* 0.0 */, 0.250,           0.500 /* 0.5 */, 0.500, 
81                    0.500 /* 0.5 */, 0.750,           1.000 /* 1.0 */, 1.000, 
82                    0.500 /* 0.5 */, 0.500,           0.500 /* 0.5 */, 0.500, 
83                    0.500 /* 0.5 */, 0.500,           0.500 /* 0.5 */, 0.500, 
84         };
85         float expected_data_red[width * height] = {
86                    0.000,           0.000 /* 0.0 */, 0.250,           0.500 /* 0.5 */, 
87                    0.500,           0.500 /* 0.5 */, 0.750,           1.000 /* 1.0 */, 
88                    0.500,           0.500 /* 0.5 */, 0.500,           0.500 /* 0.5 */, 
89                    0.500,           0.500 /* 0.5 */, 0.500,           0.500 /* 0.5 */, 
90         };
91         float out_data[width * height];
92
93         EffectChainTester tester(NULL, width, height);
94
95         ImageFormat format;
96         format.color_space = COLORSPACE_sRGB;
97         format.gamma_curve = GAMMA_sRGB;
98
99         YCbCrFormat ycbcr_format;
100         ycbcr_format.luma_coefficients = YCBCR_REC_601;
101         ycbcr_format.full_range = false;
102         ycbcr_format.chroma_subsampling_x = 2;
103         ycbcr_format.chroma_subsampling_y = 1;
104         ycbcr_format.cb_x_position = 0.0f;
105         ycbcr_format.cb_y_position = 0.5f;
106         ycbcr_format.cr_x_position = 1.0f;
107         ycbcr_format.cr_y_position = 0.5f;
108
109         YCbCr422InterleavedInput *input = new YCbCr422InterleavedInput(format, ycbcr_format, width, height);
110         input->set_pixel_data(uyvy);
111         tester.get_chain()->add_input(input);
112
113         // Y'CbCr isn't 100% accurate (the input values are rounded),
114         // so we need some leeway.
115         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_sRGB);
116         expect_equal(expected_data_red, out_data, width, height, 0.02, 0.002);
117
118         tester.run(out_data, GL_BLUE, COLORSPACE_sRGB, GAMMA_sRGB);
119         expect_equal(expected_data_blue, out_data, width, height, 0.01, 0.001);
120 }
121
122 TEST(YCbCr422InterleavedInputTest, PBO) {
123         const int width = 2;
124         const int height = 5;
125
126         // Pure-color test inputs, calculated with the formulas in Rec. 601
127         // section 2.5.4.
128         unsigned char uyvy[width * height * 2] = {
129                 /*U=*/128, /*Y=*/ 16, /*V=*/128, /*Y=*/ 16,
130                 /*U=*/128, /*Y=*/235, /*V=*/128, /*Y=*/235,
131                 /*U=*/ 90, /*Y=*/ 81, /*V=*/240, /*Y=*/ 81,
132                 /*U=*/ 54, /*Y=*/145, /*V=*/ 34, /*Y=*/145,
133                 /*U=*/240, /*Y=*/ 41, /*V=*/110, /*Y=*/ 41,
134         };
135
136         float expected_data[4 * width * height] = {
137                 0.0, 0.0, 0.0, 1.0,   0.0, 0.0, 0.0, 1.0,
138                 1.0, 1.0, 1.0, 1.0,   1.0, 1.0, 1.0, 1.0,
139                 1.0, 0.0, 0.0, 1.0,   1.0, 0.0, 0.0, 1.0,
140                 0.0, 1.0, 0.0, 1.0,   0.0, 1.0, 0.0, 1.0,
141                 0.0, 0.0, 1.0, 1.0,   0.0, 0.0, 1.0, 1.0,
142         };
143         float out_data[4 * width * height];
144
145         GLuint pbo;
146         glGenBuffers(1, &pbo);
147         glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
148         glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, width * height * 2, uyvy, GL_STREAM_DRAW);
149         glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
150
151         EffectChainTester tester(NULL, width, height);
152
153         ImageFormat format;
154         format.color_space = COLORSPACE_sRGB;
155         format.gamma_curve = GAMMA_sRGB;
156
157         YCbCrFormat ycbcr_format;
158         ycbcr_format.luma_coefficients = YCBCR_REC_601;
159         ycbcr_format.full_range = false;
160         ycbcr_format.chroma_subsampling_x = 2;
161         ycbcr_format.chroma_subsampling_y = 1;
162         ycbcr_format.cb_x_position = 0.0f;  // Doesn't really matter here, since Y is constant.
163         ycbcr_format.cb_y_position = 0.5f;
164         ycbcr_format.cr_x_position = 0.0f;
165         ycbcr_format.cr_y_position = 0.5f;
166
167         YCbCr422InterleavedInput *input = new YCbCr422InterleavedInput(format, ycbcr_format, width, height);
168         input->set_pixel_data((unsigned char *)BUFFER_OFFSET(0), pbo);
169         tester.get_chain()->add_input(input);
170
171         tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_sRGB);
172
173         // Y'CbCr isn't 100% accurate (the input values are rounded),
174         // so we need some leeway.
175         expect_equal(expected_data, out_data, 4 * width, height, 0.025, 0.002);
176
177         glDeleteBuffers(1, &pbo);
178 }
179
180 }  // namespace movit