1 /*
2 * Copyright (c) 2018, Alliance for Open Media. All rights reserved
3 *
4 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10 */
11
12 #include <string>
13 #include "third_party/googletest/src/googletest/include/gtest/gtest.h"
14 #include "aom_dsp/grain_table.h"
15 #include "aom/internal/aom_codec_internal.h"
16 #include "av1/encoder/grain_test_vectors.h"
17 #include "test/video_source.h"
18
grain_equal(const aom_film_grain_t * expected,const aom_film_grain_t * actual)19 void grain_equal(const aom_film_grain_t *expected,
20 const aom_film_grain_t *actual) {
21 EXPECT_EQ(expected->apply_grain, actual->apply_grain);
22 EXPECT_EQ(expected->update_parameters, actual->update_parameters);
23 if (!expected->update_parameters) return;
24 EXPECT_EQ(expected->num_y_points, actual->num_y_points);
25 EXPECT_EQ(expected->num_cb_points, actual->num_cb_points);
26 EXPECT_EQ(expected->num_cr_points, actual->num_cr_points);
27 EXPECT_EQ(0, memcmp(expected->scaling_points_y, actual->scaling_points_y,
28 expected->num_y_points *
29 sizeof(expected->scaling_points_y[0])));
30 EXPECT_EQ(0, memcmp(expected->scaling_points_cb, actual->scaling_points_cb,
31 expected->num_cb_points *
32 sizeof(expected->scaling_points_cb[0])));
33 EXPECT_EQ(0, memcmp(expected->scaling_points_cr, actual->scaling_points_cr,
34 expected->num_cr_points *
35 sizeof(expected->scaling_points_cr[0])));
36 EXPECT_EQ(expected->scaling_shift, actual->scaling_shift);
37 EXPECT_EQ(expected->ar_coeff_lag, actual->ar_coeff_lag);
38 EXPECT_EQ(expected->ar_coeff_shift, actual->ar_coeff_shift);
39
40 const int num_pos_luma =
41 2 * expected->ar_coeff_lag * (expected->ar_coeff_lag + 1);
42 const int num_pos_chroma = num_pos_luma;
43 EXPECT_EQ(0, memcmp(expected->ar_coeffs_y, actual->ar_coeffs_y,
44 sizeof(expected->ar_coeffs_y[0]) * num_pos_luma));
45 if (actual->num_cb_points || actual->chroma_scaling_from_luma) {
46 EXPECT_EQ(0, memcmp(expected->ar_coeffs_cb, actual->ar_coeffs_cb,
47 sizeof(expected->ar_coeffs_cb[0]) * num_pos_chroma));
48 }
49 if (actual->num_cr_points || actual->chroma_scaling_from_luma) {
50 EXPECT_EQ(0, memcmp(expected->ar_coeffs_cr, actual->ar_coeffs_cr,
51 sizeof(expected->ar_coeffs_cr[0]) * num_pos_chroma));
52 }
53 EXPECT_EQ(expected->overlap_flag, actual->overlap_flag);
54 EXPECT_EQ(expected->chroma_scaling_from_luma,
55 actual->chroma_scaling_from_luma);
56 EXPECT_EQ(expected->grain_scale_shift, actual->grain_scale_shift);
57 // EXPECT_EQ(expected->random_seed, actual->random_seed);
58
59 // clip_to_restricted and bit_depth aren't written
60 if (expected->num_cb_points) {
61 EXPECT_EQ(expected->cb_mult, actual->cb_mult);
62 EXPECT_EQ(expected->cb_luma_mult, actual->cb_luma_mult);
63 EXPECT_EQ(expected->cb_offset, actual->cb_offset);
64 }
65 if (expected->num_cr_points) {
66 EXPECT_EQ(expected->cr_mult, actual->cr_mult);
67 EXPECT_EQ(expected->cr_luma_mult, actual->cr_luma_mult);
68 EXPECT_EQ(expected->cr_offset, actual->cr_offset);
69 }
70 }
71
TEST(FilmGrainTableTest,AddAndLookupSingleSegment)72 TEST(FilmGrainTableTest, AddAndLookupSingleSegment) {
73 aom_film_grain_table_t table;
74 memset(&table, 0, sizeof(table));
75
76 aom_film_grain_t grain;
77 EXPECT_FALSE(aom_film_grain_table_lookup(&table, 0, 1000, false, &grain));
78
79 aom_film_grain_table_append(&table, 1000, 2000, film_grain_test_vectors + 0);
80 EXPECT_FALSE(aom_film_grain_table_lookup(&table, 0, 1000, false, &grain));
81 EXPECT_FALSE(aom_film_grain_table_lookup(&table, 2000, 3000, false, &grain));
82
83 EXPECT_TRUE(aom_film_grain_table_lookup(&table, 1000, 2000, false, &grain));
84
85 grain.bit_depth = film_grain_test_vectors[0].bit_depth;
86 EXPECT_EQ(0, memcmp(&grain, film_grain_test_vectors + 0, sizeof(table)));
87
88 // Extend the existing segment
89 aom_film_grain_table_append(&table, 2000, 3000, film_grain_test_vectors + 0);
90 EXPECT_EQ(0, table.head->next);
91
92 // Lookup and remove and check that the entry is no longer there
93 EXPECT_TRUE(aom_film_grain_table_lookup(&table, 1000, 2000, true, &grain));
94 EXPECT_FALSE(aom_film_grain_table_lookup(&table, 1000, 2000, false, &grain));
95
96 EXPECT_TRUE(aom_film_grain_table_lookup(&table, 2000, 3000, true, &grain));
97 EXPECT_FALSE(aom_film_grain_table_lookup(&table, 2000, 3000, false, &grain));
98
99 EXPECT_EQ(0, table.head);
100 EXPECT_EQ(0, table.tail);
101 aom_film_grain_table_free(&table);
102 }
103
TEST(FilmGrainTableTest,SplitSingleSegment)104 TEST(FilmGrainTableTest, SplitSingleSegment) {
105 aom_film_grain_table_t table;
106 aom_film_grain_t grain;
107 memset(&table, 0, sizeof(table));
108
109 aom_film_grain_table_append(&table, 0, 1000, film_grain_test_vectors + 0);
110
111 // Test lookup and remove that adjusts start time
112 EXPECT_TRUE(aom_film_grain_table_lookup(&table, 0, 100, true, &grain));
113 EXPECT_EQ(NULL, table.head->next);
114 EXPECT_EQ(100, table.head->start_time);
115
116 // Test lookup and remove that adjusts end time
117 EXPECT_TRUE(aom_film_grain_table_lookup(&table, 900, 1000, true, &grain));
118 EXPECT_EQ(NULL, table.head->next);
119 EXPECT_EQ(100, table.head->start_time);
120 EXPECT_EQ(900, table.head->end_time);
121
122 // Test lookup and remove that splits the first entry
123 EXPECT_TRUE(aom_film_grain_table_lookup(&table, 400, 600, true, &grain));
124 EXPECT_EQ(100, table.head->start_time);
125 EXPECT_EQ(400, table.head->end_time);
126
127 ASSERT_NE((void *)NULL, table.head->next);
128 EXPECT_EQ(table.tail, table.head->next);
129 EXPECT_EQ(600, table.head->next->start_time);
130 EXPECT_EQ(900, table.head->next->end_time);
131
132 aom_film_grain_table_free(&table);
133 }
134
TEST(FilmGrainTableTest,AddAndLookupMultipleSegments)135 TEST(FilmGrainTableTest, AddAndLookupMultipleSegments) {
136 aom_film_grain_table_t table;
137 memset(&table, 0, sizeof(table));
138
139 aom_film_grain_t grain;
140 const int kNumTestVectors =
141 sizeof(film_grain_test_vectors) / sizeof(film_grain_test_vectors[0]);
142 for (int i = 0; i < kNumTestVectors; ++i) {
143 aom_film_grain_table_append(&table, i * 1000, (i + 1) * 1000,
144 film_grain_test_vectors + i);
145 }
146
147 for (int i = kNumTestVectors - 1; i >= 0; --i) {
148 EXPECT_TRUE(aom_film_grain_table_lookup(&table, i * 1000, (i + 1) * 1000,
149 true, &grain));
150 grain_equal(film_grain_test_vectors + i, &grain);
151 EXPECT_FALSE(aom_film_grain_table_lookup(&table, i * 1000, (i + 1) * 1000,
152 true, &grain));
153 }
154
155 // Verify that all the data has been removed
156 for (int i = 0; i < kNumTestVectors; ++i) {
157 EXPECT_FALSE(aom_film_grain_table_lookup(&table, i * 1000, (i + 1) * 1000,
158 true, &grain));
159 }
160 aom_film_grain_table_free(&table);
161 }
162
163 class FilmGrainTableIOTest : public ::testing::Test {
164 protected:
SetUp()165 void SetUp() { memset(&error_, 0, sizeof(error_)); }
166 struct aom_internal_error_info error_;
167 };
168
TEST_F(FilmGrainTableIOTest,ReadMissingFile)169 TEST_F(FilmGrainTableIOTest, ReadMissingFile) {
170 aom_film_grain_table_t table;
171 memset(&table, 0, sizeof(table));
172 ASSERT_EQ(AOM_CODEC_ERROR, aom_film_grain_table_read(
173 &table, "/path/to/missing/file", &error_));
174 }
175
TEST_F(FilmGrainTableIOTest,ReadTruncatedFile)176 TEST_F(FilmGrainTableIOTest, ReadTruncatedFile) {
177 aom_film_grain_table_t table;
178 memset(&table, 0, sizeof(table));
179
180 std::string grain_file;
181 FILE *file = libaom_test::GetTempOutFile(&grain_file);
182 fwrite("deadbeef", 8, 1, file);
183 fclose(file);
184 ASSERT_EQ(AOM_CODEC_ERROR,
185 aom_film_grain_table_read(&table, grain_file.c_str(), &error_));
186 EXPECT_EQ(0, remove(grain_file.c_str()));
187 }
188
TEST_F(FilmGrainTableIOTest,RoundTripReadWrite)189 TEST_F(FilmGrainTableIOTest, RoundTripReadWrite) {
190 aom_film_grain_table_t table;
191 memset(&table, 0, sizeof(table));
192
193 aom_film_grain_t expected_grain[16];
194 const int kNumTestVectors =
195 sizeof(film_grain_test_vectors) / sizeof(film_grain_test_vectors[0]);
196 for (int i = 0; i < kNumTestVectors; ++i) {
197 expected_grain[i] = film_grain_test_vectors[i];
198 expected_grain[i].random_seed = i;
199 expected_grain[i].update_parameters = i % 2;
200 expected_grain[i].apply_grain = (i + 1) % 2;
201 expected_grain[i].bit_depth = 0;
202 aom_film_grain_table_append(&table, i * 1000, (i + 1) * 1000,
203 expected_grain + i);
204 }
205 std::string grain_file;
206 fclose(libaom_test::GetTempOutFile(&grain_file));
207 ASSERT_EQ(AOM_CODEC_OK,
208 aom_film_grain_table_write(&table, grain_file.c_str(), &error_));
209 aom_film_grain_table_free(&table);
210
211 memset(&table, 0, sizeof(table));
212 ASSERT_EQ(AOM_CODEC_OK,
213 aom_film_grain_table_read(&table, grain_file.c_str(), &error_));
214 for (int i = 0; i < kNumTestVectors; ++i) {
215 aom_film_grain_t grain;
216 EXPECT_TRUE(aom_film_grain_table_lookup(&table, i * 1000, (i + 1) * 1000,
217 true, &grain));
218 grain_equal(expected_grain + i, &grain);
219 }
220 aom_film_grain_table_free(&table);
221 EXPECT_EQ(0, remove(grain_file.c_str()));
222 }
223
TEST_F(FilmGrainTableIOTest,RoundTripSplit)224 TEST_F(FilmGrainTableIOTest, RoundTripSplit) {
225 std::string grain_file;
226 fclose(libaom_test::GetTempOutFile(&grain_file));
227
228 aom_film_grain_table_t table;
229 memset(&table, 0, sizeof(table));
230
231 aom_film_grain_t grain = film_grain_test_vectors[0];
232 aom_film_grain_table_append(&table, 0, 3000, &grain);
233 ASSERT_TRUE(aom_film_grain_table_lookup(&table, 1000, 2000, true, &grain));
234 ASSERT_TRUE(aom_film_grain_table_lookup(&table, 0, 1000, false, &grain));
235 EXPECT_FALSE(aom_film_grain_table_lookup(&table, 1000, 2000, false, &grain));
236 ASSERT_TRUE(aom_film_grain_table_lookup(&table, 2000, 3000, false, &grain));
237 ASSERT_EQ(AOM_CODEC_OK,
238 aom_film_grain_table_write(&table, grain_file.c_str(), &error_));
239 aom_film_grain_table_free(&table);
240
241 memset(&table, 0, sizeof(table));
242 ASSERT_EQ(AOM_CODEC_OK,
243 aom_film_grain_table_read(&table, grain_file.c_str(), &error_));
244 ASSERT_TRUE(aom_film_grain_table_lookup(&table, 0, 1000, false, &grain));
245 ASSERT_FALSE(aom_film_grain_table_lookup(&table, 1000, 2000, false, &grain));
246 ASSERT_TRUE(aom_film_grain_table_lookup(&table, 2000, 3000, false, &grain));
247 aom_film_grain_table_free(&table);
248
249 EXPECT_EQ(0, remove(grain_file.c_str()));
250 }
251