1 // Unit tests for YCbCr422InterleavedInput.
6 #include "effect_chain.h"
7 #include "gtest/gtest.h"
10 #include "ycbcr_422interleaved_input.h"
14 // Adapted from the Simple444 test from YCbCrInputTest.
15 TEST(YCbCr422InterleavedInputTest, Simple422) {
19 // Pure-color test inputs, calculated with the formulas in Rec. 601
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,
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,
36 float out_data[4 * width * height];
38 EffectChainTester tester(NULL, width, height);
41 format.color_space = COLORSPACE_sRGB;
42 format.gamma_curve = GAMMA_sRGB;
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;
54 YCbCr422InterleavedInput *input = new YCbCr422InterleavedInput(format, ycbcr_format, width, height);
55 input->set_pixel_data(uyvy);
56 tester.get_chain()->add_input(input);
58 tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_sRGB);
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);
65 // Adapted from the YCbCrInput test of the same name.
66 TEST(YCbCr422InterleavedInputTest, DifferentCbAndCrPositioning) {
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,
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,
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 */,
91 float out_data[width * height];
93 EffectChainTester tester(NULL, width, height);
96 format.color_space = COLORSPACE_sRGB;
97 format.gamma_curve = GAMMA_sRGB;
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;
109 YCbCr422InterleavedInput *input = new YCbCr422InterleavedInput(format, ycbcr_format, width, height);
110 input->set_pixel_data(uyvy);
111 tester.get_chain()->add_input(input);
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);
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);
122 TEST(YCbCr422InterleavedInputTest, PBO) {
124 const int height = 5;
126 // Pure-color test inputs, calculated with the formulas in Rec. 601
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,
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,
143 float out_data[4 * width * height];
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);
151 EffectChainTester tester(NULL, width, height);
154 format.color_space = COLORSPACE_sRGB;
155 format.gamma_curve = GAMMA_sRGB;
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;
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);
171 tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_sRGB);
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);
177 glDeleteBuffers(1, &pbo);