History

Add unit test for temporal filter on VP9

The current unit tests for temporal filtering only tests single channel version of temporal filter. Since VP9 currently uses both luma and chroma channel information for temporal filtering on low bitdepth, there is no unit case in this scenario. This commit adds some basic unit tests to facilitate further development on temporal filtering. BUG=webm:1591

chiyotsai committed 7 years ago

Commit da5e2461 parent c1827254 files · +488 −6Browse files

Unified · Split

4 files
  1. test/test.mk +1 −0
  2. test/yuv_temporal_filter_test.cc +479 −0
  3. vp9/common/vp9_rtcd_defs.pl +2 −0
  4. vp9/encoder/vp9_temporal_filter.c +6 −6
test/test.mk+1−0
@@ -171,6 +171,7 @@ LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += minmax_test.cc · 170 unmodified lines
171171 LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_scale_test.cc
172172 ifneq ($(CONFIG_REALTIME_ONLY),yes)
173173 LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += temporal_filter_test.cc
174+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += yuv_temporal_filter_test.cc
174175 endif
175176 LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += variance_test.cc
176177 LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_block_error_test.cc
test/yuv_temporal_filter_test.cc+479−0
@@ -0,0 +1,479 @@
1+/*
2+ * Copyright (c) 2019 The WebM project authors. All Rights Reserved.
3+ *
4+ * Use of this source code is governed by a BSD-style license
5+ * that can be found in the LICENSE file in the root of the source
6+ * tree. An additional intellectual property rights grant can be found
7+ * in the file PATENTS. All contributing project authors may
8+ * be found in the AUTHORS file in the root of the source tree.
9+ */
10+
11+#include <limits>
12+
13+#include "third_party/googletest/src/include/gtest/gtest.h"
14+
15+#include "./vp9_rtcd.h"
16+#include "test/acm_random.h"
17+#include "test/buffer.h"
18+#include "test/register_state_check.h"
19+#include "vpx_ports/vpx_timer.h"
20+
21+namespace {
22+
23+using ::libvpx_test::ACMRandom;
24+using ::libvpx_test::Buffer;
25+
26+typedef void (*YUVTemporalFilterFunc)(
27+ const uint8_t *y_src, int y_src_stride, const uint8_t *y_pre,
28+ int y_pre_stride, const uint8_t *u_src, const uint8_t *v_src,
29+ int uv_src_stride, const uint8_t *u_pre, const uint8_t *v_pre,
30+ int uv_pre_stride, unsigned int block_width, unsigned int block_height,
31+ int ss_x, int ss_y, int strength, const int *const blk_fw, int use_32x32,
32+ uint32_t *y_accumulator, uint16_t *y_count, uint32_t *u_accumulator,
33+ uint16_t *u_count, uint32_t *v_accumulator, uint16_t *v_count);
34+
35+static INLINE int get_filter_weight(unsigned int row, unsigned int col,
36+ unsigned int block_height,
37+ unsigned int block_width,
38+ const int *const blk_fw, int use_32x32) {
39+ if (use_32x32) {
40+ return blk_fw[0];
41+ }
42+
43+ return blk_fw[2 * (row >= block_height / 2) + (col >= block_width / 2)];
44+}
45+
46+static INLINE int mod_index(int sum_dist, int index, int rounding, int strength,
47+ int filter_weight) {
48+ int mod = (sum_dist * 3) / index;
49+ mod += rounding;
50+ mod >>= strength;
51+
52+ mod = VPXMIN(16, mod);
53+
54+ mod = 16 - mod;
55+ mod *= filter_weight;
56+
57+ return mod;
58+}
59+
60+void reference_filter(
61+ const Buffer<uint8_t> &y_src, const Buffer<uint8_t> &y_pre,
62+ const Buffer<uint8_t> &u_src, const Buffer<uint8_t> &v_src,
63+ const Buffer<uint8_t> &u_pre, const Buffer<uint8_t> &v_pre,
64+ unsigned int block_width, unsigned int block_height, int ss_x, int ss_y,
65+ int strength, const int *const blk_fw, int use_32x32,
66+ Buffer<uint32_t> *y_accumulator, Buffer<uint16_t> *y_count,
67+ Buffer<uint32_t> *u_accumulator, Buffer<uint16_t> *u_count,
68+ Buffer<uint32_t> *v_accumulator, Buffer<uint16_t> *v_count) {
69+ // blk_fw means block_filter_weight
70+ // Set up buffer to store squared_diffs
71+ Buffer<int> y_dif = Buffer<int>(block_width, block_height, 0);
72+ const int uv_block_width = block_width >> ss_x;
73+ const int uv_block_height = block_height >> ss_y;
74+ Buffer<int> u_dif = Buffer<int>(uv_block_width, uv_block_height, 0);
75+ Buffer<int> v_dif = Buffer<int>(uv_block_width, uv_block_height, 0);
76+ ASSERT_TRUE(y_dif.Init());
77+ ASSERT_TRUE(u_dif.Init());
78+ ASSERT_TRUE(v_dif.Init());
79+ y_dif.Set(0);
80+ u_dif.Set(0);
81+ v_dif.Set(0);
82+
83+ // How many bits to we want round
84+ ASSERT_GE(strength, 0);
85+ ASSERT_LE(strength, 6);
86+ int rounding = 0;
87+ if (strength > 0) {
88+ rounding = 1 << (strength - 1);
89+ }
90+
91+ // Check that the buffers are valid
92+ ASSERT_TRUE(y_src.TopLeftPixel() != NULL);
93+ ASSERT_TRUE(y_pre.TopLeftPixel() != NULL);
94+ ASSERT_TRUE(y_dif.TopLeftPixel() != NULL);
95+ ASSERT_TRUE(u_src.TopLeftPixel() != NULL);
96+ ASSERT_TRUE(u_pre.TopLeftPixel() != NULL);
97+ ASSERT_TRUE(u_dif.TopLeftPixel() != NULL);
98+ ASSERT_TRUE(v_src.TopLeftPixel() != NULL);
99+ ASSERT_TRUE(v_pre.TopLeftPixel() != NULL);
100+ ASSERT_TRUE(v_dif.TopLeftPixel() != NULL);
101+
102+ // Get the square diffs
103+ for (int row = 0; row < (int)block_height; row++) {
104+ for (int col = 0; col < (int)block_width; col++) {
105+ int diff = y_src.TopLeftPixel()[row * y_src.stride() + col] -
106+ y_pre.TopLeftPixel()[row * y_pre.stride() + col];
107+ y_dif.TopLeftPixel()[row * y_dif.stride() + col] = diff * diff;
108+ }
109+ }
110+
111+ for (int row = 0; row < uv_block_height; row++) {
112+ for (int col = 0; col < uv_block_width; col++) {
113+ int u_diff = u_src.TopLeftPixel()[row * u_src.stride() + col] -
114+ u_pre.TopLeftPixel()[row * u_pre.stride() + col];
115+ int v_diff = v_src.TopLeftPixel()[row * v_src.stride() + col] -
116+ v_pre.TopLeftPixel()[row * v_pre.stride() + col];
117+ u_dif.TopLeftPixel()[row * u_dif.stride() + col] = u_diff * u_diff;
118+ v_dif.TopLeftPixel()[row * v_dif.stride() + col] = v_diff * v_diff;
119+ }
120+ }
121+
122+ // Apply the filter
123+ for (int row = 0; row < (int)block_height; row++) {
124+ for (int col = 0; col < (int)block_width; col++) {
125+ const int uv_r = row >> ss_y;
126+ const int uv_c = col >> ss_x;
127+ int filter_weight = get_filter_weight(row, col, block_height, block_width,
128+ blk_fw, use_32x32);
129+
130+ // First we get the modifier for the current y pixel
131+ const int y_pixel = y_pre.TopLeftPixel()[row * y_pre.stride() + col];
132+ int y_num_used = 0;
133+ int y_mod = 0;
134+
135+ // Sum the neighboring 3x3 y pixels
136+ for (int row_step = -1; row_step <= 1; row_step++) {
137+ for (int col_step = -1; col_step <= 1; col_step++) {
138+ const int sub_row = row + row_step;
139+ const int sub_col = col + col_step;
140+
141+ if (sub_row >= 0 && sub_row < (int)block_height && sub_col >= 0 &&
142+ sub_col < (int)block_width) {
143+ y_mod += y_dif.TopLeftPixel()[sub_row * y_dif.stride() + sub_col];
144+ y_num_used++;
145+ }
146+ }
147+ }
148+
149+ ASSERT_GE(y_num_used, 0);
150+
151+ // Sum the corresponding uv pixels to the current y modifier
152+ // Note we are rounding down instead of rounding to the nearest pixel.
153+ y_mod += u_dif.TopLeftPixel()[uv_r * uv_block_width + uv_c];
154+ y_mod += v_dif.TopLeftPixel()[uv_r * uv_block_width + uv_c];
155+
156+ y_num_used += 2;
157+
158+ // Set the modifier
159+ y_mod = mod_index(y_mod, y_num_used, rounding, strength, filter_weight);
160+
161+ // Accumulate the result
162+ y_count->TopLeftPixel()[row * y_count->stride() + col] += y_mod;
163+ y_accumulator->TopLeftPixel()[row * y_accumulator->stride() + col] +=
164+ y_mod * y_pixel;
165+
166+ // Get the modifier for chroma components
167+ if (!(row & ss_y) && !(col & ss_x)) {
168+ const int u_pixel = u_pre.TopLeftPixel()[uv_r * u_pre.stride() + uv_c];
169+ const int v_pixel = v_pre.TopLeftPixel()[uv_r * v_pre.stride() + uv_c];
170+
171+ int uv_num_used = 0;
172+ int u_mod = 0, v_mod = 0;
173+
174+ // Sum the neighboring 3x3 chromal pixels to the chroma modifier
175+ for (int row_step = -1; row_step <= 1; row_step++) {
176+ for (int col_step = -1; col_step <= 1; col_step++) {
177+ const int sub_row = uv_r + row_step;
178+ const int sub_col = uv_c + col_step;
179+
180+ if (sub_row >= 0 && sub_row < uv_block_height && sub_col >= 0 &&
181+ sub_col < uv_block_width) {
182+ u_mod += u_dif.TopLeftPixel()[sub_row * uv_block_width + sub_col];
183+ v_mod += v_dif.TopLeftPixel()[sub_row * uv_block_width + sub_col];
184+ uv_num_used++;
185+ }
186+ }
187+ }
188+
189+ assert(uv_num_used > 0);
190+
191+ // Sum all the luma pixels associated with the current luma pixel
192+ for (int row_step = 0; row_step < 1 + ss_y; row_step++) {
193+ for (int col_step = 0; col_step < 1 + ss_x; col_step++) {
194+ const int sub_row = (uv_r << ss_y) + row_step;
195+ const int sub_col = (uv_c << ss_x) + col_step;
196+ const int y_diff =
197+ y_dif.TopLeftPixel()[sub_row * y_dif.stride() + sub_col];
198+
199+ u_mod += y_diff;
200+ v_mod += y_diff;
201+ uv_num_used++;
202+ }
203+ }
204+
205+ // Set the modifier
206+ u_mod =
207+ mod_index(u_mod, uv_num_used, rounding, strength, filter_weight);
208+ v_mod =
209+ mod_index(v_mod, uv_num_used, rounding, strength, filter_weight);
210+
211+ // Accumuate the result
212+ u_count->TopLeftPixel()[uv_r * u_count->stride() + uv_c] += u_mod;
213+ u_accumulator->TopLeftPixel()[uv_r * u_accumulator->stride() + uv_c] +=
214+ u_mod * u_pixel;
215+ v_count->TopLeftPixel()[uv_r * u_count->stride() + uv_c] += v_mod;
216+ v_accumulator->TopLeftPixel()[uv_r * v_accumulator->stride() + uv_c] +=
217+ v_mod * v_pixel;
218+ }
219+ }
220+ }
221+}
222+
223+class YUVTemporalFilterTest
224+ : public ::testing::TestWithParam<YUVTemporalFilterFunc> {
225+ public:
226+ virtual void SetUp() {
227+ filter_func_ = GetParam();
228+ rnd_.Reset(ACMRandom::DeterministicSeed());
229+ }
230+
231+ protected:
232+ YUVTemporalFilterFunc filter_func_;
233+ ACMRandom rnd_;
234+};
235+
236+TEST_P(YUVTemporalFilterTest, USE_32X32) {
237+ const int width = 32, height = 32;
238+ Buffer<uint8_t> y_src = Buffer<uint8_t>(width, height, 8);
239+ Buffer<uint8_t> y_pre = Buffer<uint8_t>(width, height, 0);
240+ Buffer<uint16_t> y_count_ref = Buffer<uint16_t>(width, height, 0);
241+ Buffer<uint32_t> y_accum_ref = Buffer<uint32_t>(width, height, 0);
242+ Buffer<uint16_t> y_count_tst = Buffer<uint16_t>(width, height, 0);
243+ Buffer<uint32_t> y_accum_tst = Buffer<uint32_t>(width, height, 0);
244+ ASSERT_TRUE(y_src.Init());
245+ ASSERT_TRUE(y_pre.Init());
246+ ASSERT_TRUE(y_count_ref.Init());
247+ ASSERT_TRUE(y_accum_ref.Init());
248+ ASSERT_TRUE(y_count_tst.Init());
249+ ASSERT_TRUE(y_accum_tst.Init());
250+
251+ const int use_32x32 = 1;
252+
253+ for (int ss_x = 0; ss_x <= 1; ss_x++) {
254+ for (int ss_y = 0; ss_y <= 1; ss_y++) {
255+ for (int filter_strength = 0; filter_strength <= 6;
256+ filter_strength += 2) {
257+ for (int filter_weight = 0; filter_weight <= 2; filter_weight++) {
258+ const int uv_width = width >> ss_x, uv_height = height >> ss_y;
259+ Buffer<uint8_t> u_src = Buffer<uint8_t>(uv_width, uv_height, 8);
260+ Buffer<uint8_t> u_pre = Buffer<uint8_t>(uv_width, uv_height, 0);
261+ Buffer<uint16_t> u_count_ref =
262+ Buffer<uint16_t>(uv_width, uv_height, 0);
263+ Buffer<uint32_t> u_accum_ref =
264+ Buffer<uint32_t>(uv_width, uv_height, 0);
265+ Buffer<uint16_t> u_count_tst =
266+ Buffer<uint16_t>(uv_width, uv_height, 0);
267+ Buffer<uint32_t> u_accum_tst =
268+ Buffer<uint32_t>(uv_width, uv_height, 0);
269+ ASSERT_TRUE(u_src.Init());
270+ ASSERT_TRUE(u_pre.Init());
271+ ASSERT_TRUE(u_count_ref.Init());
272+ ASSERT_TRUE(u_accum_ref.Init());
273+ ASSERT_TRUE(u_count_tst.Init());
274+ ASSERT_TRUE(u_accum_tst.Init());
275+ Buffer<uint8_t> v_src = Buffer<uint8_t>(uv_width, uv_height, 8);
276+ Buffer<uint8_t> v_pre = Buffer<uint8_t>(uv_width, uv_height, 0);
277+ Buffer<uint16_t> v_count_ref =
278+ Buffer<uint16_t>(uv_width, uv_height, 0);
279+ Buffer<uint32_t> v_accum_ref =
280+ Buffer<uint32_t>(uv_width, uv_height, 0);
281+ Buffer<uint16_t> v_count_tst =
282+ Buffer<uint16_t>(uv_width, uv_height, 0);
283+ Buffer<uint32_t> v_accum_tst =
284+ Buffer<uint32_t>(uv_width, uv_height, 0);
285+ ASSERT_TRUE(v_src.Init());
286+ ASSERT_TRUE(v_pre.Init());
287+ ASSERT_TRUE(v_count_ref.Init());
288+ ASSERT_TRUE(v_accum_ref.Init());
289+ ASSERT_TRUE(v_count_tst.Init());
290+ ASSERT_TRUE(v_accum_tst.Init());
291+
292+ // The difference between the buffers must be small to pass the
293+ // threshold to apply the filter.
294+ y_src.Set(&rnd_, 0, 7);
295+ y_pre.Set(&rnd_, 0, 7);
296+ u_src.Set(&rnd_, 0, 7);
297+ u_pre.Set(&rnd_, 0, 7);
298+ v_src.Set(&rnd_, 0, 7);
299+ v_pre.Set(&rnd_, 0, 7);
300+
301+ y_accum_ref.Set(rnd_.Rand8());
302+ y_accum_tst.CopyFrom(y_accum_ref);
303+ y_count_ref.Set(rnd_.Rand8());
304+ y_count_tst.CopyFrom(y_count_ref);
305+ u_accum_ref.Set(rnd_.Rand8());
306+ u_accum_tst.CopyFrom(u_accum_ref);
307+ u_count_ref.Set(rnd_.Rand8());
308+ u_count_tst.CopyFrom(u_count_ref);
309+ v_accum_ref.Set(rnd_.Rand8());
310+ v_accum_tst.CopyFrom(v_accum_ref);
311+ v_count_ref.Set(rnd_.Rand8());
312+ v_count_tst.CopyFrom(v_count_ref);
313+
314+ reference_filter(y_src, y_pre, u_src, v_src, u_pre, v_pre, width,
315+ height, ss_x, ss_y, filter_strength, &filter_weight,
316+ use_32x32, &y_accum_ref, &y_count_ref, &u_accum_ref,
317+ &u_count_ref, &v_accum_ref, &v_count_ref);
318+ ASM_REGISTER_STATE_CHECK(filter_func_(
319+ y_src.TopLeftPixel(), y_src.stride(), y_pre.TopLeftPixel(),
320+ y_pre.stride(), u_src.TopLeftPixel(), v_src.TopLeftPixel(),
321+ u_src.stride(), u_pre.TopLeftPixel(), v_pre.TopLeftPixel(),
322+ u_pre.stride(), width, height, ss_x, ss_y, filter_strength,
323+ &filter_weight, use_32x32, y_accum_tst.TopLeftPixel(),
324+ y_count_tst.TopLeftPixel(), u_accum_tst.TopLeftPixel(),
325+ u_count_tst.TopLeftPixel(), v_accum_tst.TopLeftPixel(),
326+ v_count_tst.TopLeftPixel()));
327+
328+ EXPECT_TRUE(y_accum_tst.CheckValues(y_accum_ref));
329+ EXPECT_TRUE(y_count_tst.CheckValues(y_count_ref));
330+ EXPECT_TRUE(u_accum_tst.CheckValues(u_accum_ref));
331+ EXPECT_TRUE(u_count_tst.CheckValues(u_count_ref));
332+ EXPECT_TRUE(v_accum_tst.CheckValues(v_accum_ref));
333+ EXPECT_TRUE(v_count_tst.CheckValues(v_count_ref));
334+
335+ if (HasFailure()) {
336+ printf("SS_X: %d, SS_Y: %d, Weight: %d, Strength: %d\n", ss_x, ss_y,
337+ filter_weight, filter_strength);
338+ y_accum_tst.PrintDifference(y_accum_ref);
339+ y_count_tst.PrintDifference(y_count_ref);
340+ u_accum_tst.PrintDifference(u_accum_ref);
341+ u_count_tst.PrintDifference(u_count_ref);
342+ v_accum_tst.PrintDifference(v_accum_ref);
343+ v_count_tst.PrintDifference(v_count_ref);
344+ return;
345+ }
346+ }
347+ }
348+ }
349+ }
350+}
351+
352+TEST_P(YUVTemporalFilterTest, USE_16X16) {
353+ const int width = 32, height = 32;
354+ Buffer<uint8_t> y_src = Buffer<uint8_t>(width, height, 8);
355+ Buffer<uint8_t> y_pre = Buffer<uint8_t>(width, height, 0);
356+ Buffer<uint16_t> y_count_ref = Buffer<uint16_t>(width, height, 0);
357+ Buffer<uint32_t> y_accum_ref = Buffer<uint32_t>(width, height, 0);
358+ Buffer<uint16_t> y_count_tst = Buffer<uint16_t>(width, height, 0);
359+ Buffer<uint32_t> y_accum_tst = Buffer<uint32_t>(width, height, 0);
360+ ASSERT_TRUE(y_src.Init());
361+ ASSERT_TRUE(y_pre.Init());
362+ ASSERT_TRUE(y_count_ref.Init());
363+ ASSERT_TRUE(y_accum_ref.Init());
364+ ASSERT_TRUE(y_count_tst.Init());
365+ ASSERT_TRUE(y_accum_tst.Init());
366+
367+ const int use_32x32 = 0;
368+
369+ for (int ss_x = 0; ss_x <= 1; ss_x++) {
370+ for (int ss_y = 0; ss_y <= 1; ss_y++) {
371+ for (int filter_idx = 0; filter_idx < 3 * 3 * 3 * 3; filter_idx++) {
372+ // Set up the filter
373+ int filter_weight[4];
374+ int filter_idx_cp = filter_idx;
375+ for (int idx = 0; idx < 4; idx++) {
376+ filter_weight[idx] = filter_idx_cp % 3;
377+ filter_idx_cp /= 3;
378+ }
379+
380+ // Test each parameter
381+ for (int filter_strength = 0; filter_strength <= 6;
382+ filter_strength += 2) {
383+ const int uv_width = width >> ss_x, uv_height = height >> ss_y;
384+ Buffer<uint8_t> u_src = Buffer<uint8_t>(uv_width, uv_height, 8);
385+ Buffer<uint8_t> u_pre = Buffer<uint8_t>(uv_width, uv_height, 0);
386+ Buffer<uint16_t> u_count_ref =
387+ Buffer<uint16_t>(uv_width, uv_height, 0);
388+ Buffer<uint32_t> u_accum_ref =
389+ Buffer<uint32_t>(uv_width, uv_height, 0);
390+ Buffer<uint16_t> u_count_tst =
391+ Buffer<uint16_t>(uv_width, uv_height, 0);
392+ Buffer<uint32_t> u_accum_tst =
393+ Buffer<uint32_t>(uv_width, uv_height, 0);
394+ ASSERT_TRUE(u_src.Init());
395+ ASSERT_TRUE(u_pre.Init());
396+ ASSERT_TRUE(u_count_ref.Init());
397+ ASSERT_TRUE(u_accum_ref.Init());
398+ ASSERT_TRUE(u_count_tst.Init());
399+ ASSERT_TRUE(u_accum_tst.Init());
400+ Buffer<uint8_t> v_src = Buffer<uint8_t>(uv_width, uv_height, 8);
401+ Buffer<uint8_t> v_pre = Buffer<uint8_t>(uv_width, uv_height, 0);
402+ Buffer<uint16_t> v_count_ref =
403+ Buffer<uint16_t>(uv_width, uv_height, 0);
404+ Buffer<uint32_t> v_accum_ref =
405+ Buffer<uint32_t>(uv_width, uv_height, 0);
406+ Buffer<uint16_t> v_count_tst =
407+ Buffer<uint16_t>(uv_width, uv_height, 0);
408+ Buffer<uint32_t> v_accum_tst =
409+ Buffer<uint32_t>(uv_width, uv_height, 0);
410+ ASSERT_TRUE(v_src.Init());
411+ ASSERT_TRUE(v_pre.Init());
412+ ASSERT_TRUE(v_count_ref.Init());
413+ ASSERT_TRUE(v_accum_ref.Init());
414+ ASSERT_TRUE(v_count_tst.Init());
415+ ASSERT_TRUE(v_accum_tst.Init());
416+
417+ // The difference between the buffers must be small to pass the
418+ // threshold to apply the filter.
419+ y_src.Set(&rnd_, 0, 7);
420+ y_pre.Set(&rnd_, 0, 7);
421+ u_src.Set(&rnd_, 0, 7);
422+ u_pre.Set(&rnd_, 0, 7);
423+ v_src.Set(&rnd_, 0, 7);
424+ v_pre.Set(&rnd_, 0, 7);
425+
426+ y_accum_ref.Set(rnd_.Rand8());
427+ y_accum_tst.CopyFrom(y_accum_ref);
428+ y_count_ref.Set(rnd_.Rand8());
429+ y_count_tst.CopyFrom(y_count_ref);
430+ u_accum_ref.Set(rnd_.Rand8());
431+ u_accum_tst.CopyFrom(u_accum_ref);
432+ u_count_ref.Set(rnd_.Rand8());
433+ u_count_tst.CopyFrom(u_count_ref);
434+ v_accum_ref.Set(rnd_.Rand8());
435+ v_accum_tst.CopyFrom(v_accum_ref);
436+ v_count_ref.Set(rnd_.Rand8());
437+ v_count_tst.CopyFrom(v_count_ref);
438+
439+ reference_filter(y_src, y_pre, u_src, v_src, u_pre, v_pre, width,
440+ height, ss_x, ss_y, filter_strength, filter_weight,
441+ use_32x32, &y_accum_ref, &y_count_ref, &u_accum_ref,
442+ &u_count_ref, &v_accum_ref, &v_count_ref);
443+ ASM_REGISTER_STATE_CHECK(filter_func_(
444+ y_src.TopLeftPixel(), y_src.stride(), y_pre.TopLeftPixel(),
445+ y_pre.stride(), u_src.TopLeftPixel(), v_src.TopLeftPixel(),
446+ u_src.stride(), u_pre.TopLeftPixel(), v_pre.TopLeftPixel(),
447+ u_pre.stride(), width, height, ss_x, ss_y, filter_strength,
448+ filter_weight, use_32x32, y_accum_tst.TopLeftPixel(),
449+ y_count_tst.TopLeftPixel(), u_accum_tst.TopLeftPixel(),
450+ u_count_tst.TopLeftPixel(), v_accum_tst.TopLeftPixel(),
451+ v_count_tst.TopLeftPixel()));
452+
453+ EXPECT_TRUE(y_accum_tst.CheckValues(y_accum_ref));
454+ EXPECT_TRUE(y_count_tst.CheckValues(y_count_ref));
455+ EXPECT_TRUE(u_accum_tst.CheckValues(u_accum_ref));
456+ EXPECT_TRUE(u_count_tst.CheckValues(u_count_ref));
457+ EXPECT_TRUE(v_accum_tst.CheckValues(v_accum_ref));
458+ EXPECT_TRUE(v_count_tst.CheckValues(v_count_ref));
459+
460+ if (HasFailure()) {
461+ printf("SS_X: %d, SS_Y: %d, Weight Idx: %d, Strength: %d\n", ss_x,
462+ ss_y, filter_idx, filter_strength);
463+ y_accum_tst.PrintDifference(y_accum_ref);
464+ y_count_tst.PrintDifference(y_count_ref);
465+ u_accum_tst.PrintDifference(u_accum_ref);
466+ u_count_tst.PrintDifference(u_count_ref);
467+ v_accum_tst.PrintDifference(v_accum_ref);
468+ v_count_tst.PrintDifference(v_count_ref);
469+ return;
470+ }
471+ }
472+ }
473+ }
474+ }
475+}
476+
477+INSTANTIATE_TEST_CASE_P(C, YUVTemporalFilterTest,
478+ ::testing::Values(&vp9_apply_temporal_filter));
479+} // namespace
vp9/common/vp9_rtcd_defs.pl+2−0
@@ -186,6 +186,8 @@ specialize qw/vp9_diamond_search_sad avx/; · 185 unmodified lines
186186 if (vpx_config("CONFIG_REALTIME_ONLY") ne "yes") {
187187 add_proto qw/void vp9_temporal_filter_apply/, "const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count";
188188 specialize qw/vp9_temporal_filter_apply sse4_1/;
189+
190+add_proto qw/void vp9_apply_temporal_filter/, "const uint8_t *y_src, int y_src_stride, const uint8_t *y_pre, int y_pre_stride, const uint8_t *u_src, const uint8_t *v_src, int uv_src_stride, const uint8_t *u_pre, const uint8_t *v_pre, int uv_pre_stride, unsigned int block_width, unsigned int block_height, int ss_x, int ss_y, int strength, const int *const blk_fw, int use_32x32, uint32_t *y_accumulator, uint16_t *y_count, uint32_t *u_accumulator, uint16_t *u_count, uint32_t *v_accumulator, uint16_t *v_count";
189191 }
190192
191193 if (vpx_config("CONFIG_VP9_HIGHBITDEPTH") eq "yes") {
vp9/encoder/vp9_temporal_filter.c+6−6
@@ -198,8 +198,8 @@ static INLINE int mod_index(int sum_dist, int index, int rounding, int strength, · 197 unmodified lines
198198
199199 static INLINE int get_filter_weight(unsigned int i, unsigned int j,
200200 unsigned int block_height,
201− unsigned int block_width, int *blk_fw,
202− int use_32x32) {
201+ unsigned int block_width,
202+ const int *const blk_fw, int use_32x32) {
203203 int filter_weight = 0;
204204
205205 if (use_32x32)
@@ -220,12 +220,12 @@ static INLINE int get_filter_weight(unsigned int i, unsigned int j, · 14 unmodified lines
220220 return filter_weight;
221221 }
222222
223−static void apply_temporal_filter(
223+void vp9_apply_temporal_filter_c(
224224 const uint8_t *y_frame1, int y_stride, const uint8_t *y_pred,
225225 int y_buf_stride, const uint8_t *u_frame1, const uint8_t *v_frame1,
226226 int uv_stride, const uint8_t *u_pred, const uint8_t *v_pred,
227227 int uv_buf_stride, unsigned int block_width, unsigned int block_height,
228− int ss_x, int ss_y, int strength, int *blk_fw, int use_32x32,
228+ int ss_x, int ss_y, int strength, const int *const blk_fw, int use_32x32,
229229 uint32_t *y_accumulator, uint16_t *y_count, uint32_t *u_accumulator,
230230 uint16_t *u_count, uint32_t *v_accumulator, uint16_t *v_count) {
231231 unsigned int i, j, k, m;
@@ -767,7 +767,7 @@ void vp9_temporal_filter_iterate_row_c(VP9_COMP *cpi, ThreadData *td, · 535 unmodified lines
767767 count + (BLK_PELS << 1));
768768 } else {
769769 // Apply the filter (YUV)
770− apply_temporal_filter(
770+ vp9_apply_temporal_filter_c(
771771 f->y_buffer + mb_y_offset, f->y_stride, predictor, BW,
772772 f->u_buffer + mb_uv_offset, f->v_buffer + mb_uv_offset,
773773 f->uv_stride, predictor + BLK_PELS, predictor + (BLK_PELS << 1),
@@ -778,7 +778,7 @@ void vp9_temporal_filter_iterate_row_c(VP9_COMP *cpi, ThreadData *td, · 4 unmodified lines
778778 }
779779 #else
780780 // Apply the filter (YUV)
781− apply_temporal_filter(
781+ vp9_apply_temporal_filter_c(
782782 f->y_buffer + mb_y_offset, f->y_stride, predictor, BW,
783783 f->u_buffer + mb_uv_offset, f->v_buffer + mb_uv_offset,
784784 f->uv_stride, predictor + BLK_PELS, predictor + (BLK_PELS << 1),

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t