1 // Unit tests for DeinterlaceEffect.
7 #include "effect_chain.h"
8 #include "gtest/gtest.h"
9 #include "image_format.h"
11 #include "deinterlace_effect.h"
12 #include "test_util.h"
18 TEST(DeinterlaceTest, ConstantColor) {
24 float expected_data[] = {
33 EffectChainTester tester(NULL, 2, 6);
34 Effect *input1 = tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, 2, 3);
35 Effect *input2 = tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, 2, 3);
36 Effect *input3 = tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, 2, 3);
37 Effect *input4 = tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, 2, 3);
38 Effect *input5 = tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, 2, 3);
39 Effect *deinterlace_effect = tester.get_chain()->add_effect(new DeinterlaceEffect(), input1, input2, input3, input4, input5);
41 ASSERT_TRUE(deinterlace_effect->set_int("current_field_position", 0));
42 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
43 expect_equal(expected_data, out_data, 2, 6);
45 ASSERT_TRUE(deinterlace_effect->set_int("current_field_position", 1));
46 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
47 expect_equal(expected_data, out_data, 2, 6);
50 // Also tests that top/bottom change works like expected.
51 TEST(DeinterlaceTest, VerticalInterpolation) {
54 float data[width * height] = {
55 0.0f, 0.0f, 0.0f, 0.4f, 0.6f, 0.2f, 0.6f, 0.8f, 0.0f, 0.0f, 0.0f,
56 0.0f, 0.0f, 0.0f, 0.4f, 0.6f, 0.4f, 0.6f, 0.8f, 0.0f, 0.0f, 0.0f, // Differs from previous.
58 float expected_data_top[width * height * 2] = {
59 0.0f, 0.0f, 0.0f, 0.4f, 0.6f, 0.2f, 0.6f, 0.8f, 0.0f, 0.0f, 0.0f, // Unchanged.
60 0.0f, 0.0f, 0.0f, 0.4f, 0.6f, 0.3f, 0.6f, 0.8f, 0.0f, 0.0f, 0.0f,
61 0.0f, 0.0f, 0.0f, 0.4f, 0.6f, 0.4f, 0.6f, 0.8f, 0.0f, 0.0f, 0.0f, // Unchanged.
62 0.0f, 0.0f, 0.0f, 0.4f, 0.6f, 0.4f, 0.6f, 0.8f, 0.0f, 0.0f, 0.0f, // Repeated.
64 float expected_data_bottom[width * height * 2] = {
65 0.0f, 0.0f, 0.0f, 0.4f, 0.6f, 0.2f, 0.6f, 0.8f, 0.0f, 0.0f, 0.0f, // Repeated
66 0.0f, 0.0f, 0.0f, 0.4f, 0.6f, 0.2f, 0.6f, 0.8f, 0.0f, 0.0f, 0.0f, // Unchanged.
67 0.0f, 0.0f, 0.0f, 0.4f, 0.6f, 0.3f, 0.6f, 0.8f, 0.0f, 0.0f, 0.0f,
68 0.0f, 0.0f, 0.0f, 0.4f, 0.6f, 0.4f, 0.6f, 0.8f, 0.0f, 0.0f, 0.0f, // Unchanged.
70 float neg_blowout_data[width * height];
71 float pos_blowout_data[width * height];
72 float out_data[width * height * 2];
74 // Set previous and next fields to something so big that all the temporal checks
75 // are effectively turned off.
76 fill(neg_blowout_data, neg_blowout_data + width * height, -100.0f);
77 fill(neg_blowout_data, pos_blowout_data + width * height, 100.0f);
79 EffectChainTester tester(NULL, width, height * 2);
80 Effect *input1 = tester.add_input(neg_blowout_data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
81 Effect *input2 = tester.add_input(neg_blowout_data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
82 Effect *input3 = tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
83 Effect *input4 = tester.add_input(pos_blowout_data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
84 Effect *input5 = tester.add_input(pos_blowout_data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
85 Effect *deinterlace_effect = tester.get_chain()->add_effect(new DeinterlaceEffect(), input1, input2, input3, input4, input5);
87 ASSERT_TRUE(deinterlace_effect->set_int("current_field_position", 0));
88 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
89 expect_equal(expected_data_top, out_data, width, height * 2);
91 ASSERT_TRUE(deinterlace_effect->set_int("current_field_position", 1));
92 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
93 expect_equal(expected_data_bottom, out_data, width, height * 2);
96 TEST(DeinterlaceTest, DiagonalInterpolation) {
99 float data[width * height] = {
100 0.0f, 0.0f, 0.0f, 0.0f, 0.4f, 0.6f, 0.2f, 0.6f, 0.8f, 0.0f, 0.0f,
101 0.0f, 0.0f, 0.4f, 0.6f, 0.4f, 0.6f, 0.8f, 0.0f, 0.0f, 0.0f, 0.0f, // Offset two pixels, one value modified.
102 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.4f, 0.6f, 0.4f, 0.6f, 0.8f, // Offset four the other way.
105 // Expected degrees are marked in comments. Mostly we want +45 for the second line
106 // and -63 for the fourth, but due to the score being over three neighboring pixels,
107 // sometimes it doesn't work ideally like that.
108 float expected_data_top[width * height * 2] = {
109 0.0f, 0.0f, 0.0f, 0.0f, 0.4f, 0.6f, 0.2f, 0.6f, 0.8f, 0.0f, 0.0f, // Unchanged.
110 // | / / / / / / / / / |
111 // 0 +45 +45 +45 +45 +45 +45 +45 +45 +45 0
112 0.0f, 0.0f, 0.0f, 0.4f, 0.6f, 0.3f, 0.6f, 0.8f, 0.0f, 0.0f, 0.0f,
113 // | / / / / / / / / / |
114 0.0f, 0.0f, 0.4f, 0.6f, 0.4f, 0.6f, 0.8f, 0.0f, 0.0f, 0.0f, 0.0f, // Unchanged.
116 // 0 -45 -63 -63 -63 -63 -63 -63 +63! +63! +63!
117 0.0f, 0.0f, 0.0f, 0.0f, 0.4f, 0.6f, 0.4f, 0.6f, 0.2f, 0.3f, 0.2f,
119 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.4f, 0.6f, 0.4f, 0.6f, 0.8f, // Unchanged.
120 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.4f, 0.6f, 0.4f, 0.6f, 0.8f, // Repeated.
122 float neg_blowout_data[width * height];
123 float pos_blowout_data[width * height];
124 float out_data[width * height * 2];
126 // Set previous and next fields to something so big that all the temporal checks
127 // are effectively turned off.
128 fill(neg_blowout_data, neg_blowout_data + width * height, -100.0f);
129 fill(pos_blowout_data, pos_blowout_data + width * height, 100.0f);
131 EffectChainTester tester(NULL, width, height * 2);
132 Effect *input1 = tester.add_input(neg_blowout_data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
133 Effect *input2 = tester.add_input(neg_blowout_data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
134 Effect *input3 = tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
135 Effect *input4 = tester.add_input(pos_blowout_data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
136 Effect *input5 = tester.add_input(pos_blowout_data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
137 Effect *deinterlace_effect = tester.get_chain()->add_effect(new DeinterlaceEffect(), input1, input2, input3, input4, input5);
139 ASSERT_TRUE(deinterlace_effect->set_int("current_field_position", 0));
140 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR, OUTPUT_ALPHA_FORMAT_PREMULTIPLIED);
141 expect_equal(expected_data_top, out_data, width, height * 2);
144 TEST(DeinterlaceTest, FlickerBox) {
146 const int height = 4;
147 float white_data[width * height] = {
148 1.0f, 1.0f, 1.0f, 1.0f,
149 1.0f, 1.0f, 1.0f, 1.0f,
150 1.0f, 1.0f, 1.0f, 1.0f,
151 1.0f, 1.0f, 1.0f, 1.0f,
153 float black_data[width * height] = {
154 0.0f, 0.0f, 0.0f, 0.0f,
155 0.0f, 0.0f, 0.0f, 0.0f,
156 0.0f, 0.0f, 0.0f, 0.0f,
157 0.0f, 0.0f, 0.0f, 0.0f,
159 float striped_data[width * height * 2] = {
160 1.0f, 1.0f, 1.0f, 1.0f,
161 0.0f, 0.0f, 0.0f, 0.0f,
162 1.0f, 1.0f, 1.0f, 1.0f,
163 0.0f, 0.0f, 0.0f, 0.0f,
164 1.0f, 1.0f, 1.0f, 1.0f,
165 0.0f, 0.0f, 0.0f, 0.0f,
166 1.0f, 1.0f, 1.0f, 1.0f,
167 0.0f, 0.0f, 0.0f, 0.0f,
169 float out_data[width * height * 2];
172 EffectChainTester tester(NULL, width, height * 2);
173 Effect *white_input = tester.add_input(white_data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
174 Effect *black_input = tester.add_input(black_data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
175 Effect *deinterlace_effect = tester.get_chain()->add_effect(new DeinterlaceEffect(), white_input, black_input, white_input, black_input, white_input);
177 ASSERT_TRUE(deinterlace_effect->set_int("current_field_position", 0));
178 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR, OUTPUT_ALPHA_FORMAT_PREMULTIPLIED);
179 expect_equal(white_data, out_data, width, height);
180 expect_equal(white_data, out_data + width * height, width, height);
184 EffectChainTester tester(NULL, width, height * 2);
185 Effect *white_input = tester.add_input(white_data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
186 Effect *black_input = tester.add_input(black_data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
187 Effect *deinterlace_effect = tester.get_chain()->add_effect(new DeinterlaceEffect(), white_input, black_input, white_input, black_input, white_input);
189 ASSERT_TRUE(deinterlace_effect->set_int("enable_spatial_interlacing_check", 0));
190 ASSERT_TRUE(deinterlace_effect->set_int("current_field_position", 0));
191 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR, OUTPUT_ALPHA_FORMAT_PREMULTIPLIED);
192 expect_equal(striped_data, out_data, width, height * 2);