blob: c71097ac26accb1d60077205508d0b2c159ab4b2 [file] [log] [blame]
jackychen67e94fb2016-01-11 21:34:07 -08001/*
2 * Copyright (c) 2015 The WebRTC 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 <string.h>
12
kwiberge065fcf2016-03-02 01:01:11 -080013#include <memory>
14
jackychen67e94fb2016-01-11 21:34:07 -080015#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
16#include "webrtc/modules/video_processing/include/video_processing.h"
17#include "webrtc/modules/video_processing/test/video_processing_unittest.h"
18#include "webrtc/modules/video_processing/video_denoiser.h"
Niels Möller739fcb92016-02-29 13:11:45 +010019#include "webrtc/test/frame_utils.h"
jackychen67e94fb2016-01-11 21:34:07 -080020
21namespace webrtc {
22
23TEST_F(VideoProcessingTest, CopyMem) {
kwiberge065fcf2016-03-02 01:01:11 -080024 std::unique_ptr<DenoiserFilter> df_c(DenoiserFilter::Create(false));
25 std::unique_ptr<DenoiserFilter> df_sse_neon(DenoiserFilter::Create(true));
jackychen67e94fb2016-01-11 21:34:07 -080026 uint8_t src[16 * 16], dst[16 * 16];
27 for (int i = 0; i < 16; ++i) {
28 for (int j = 0; j < 16; ++j) {
29 src[i * 16 + j] = i * 16 + j;
30 }
31 }
32
33 memset(dst, 0, 8 * 8);
34 df_c->CopyMem8x8(src, 8, dst, 8);
35 EXPECT_EQ(0, memcmp(src, dst, 8 * 8));
36
37 memset(dst, 0, 16 * 16);
38 df_c->CopyMem16x16(src, 16, dst, 16);
39 EXPECT_EQ(0, memcmp(src, dst, 16 * 16));
40
41 memset(dst, 0, 8 * 8);
42 df_sse_neon->CopyMem16x16(src, 8, dst, 8);
43 EXPECT_EQ(0, memcmp(src, dst, 8 * 8));
44
45 memset(dst, 0, 16 * 16);
46 df_sse_neon->CopyMem16x16(src, 16, dst, 16);
47 EXPECT_EQ(0, memcmp(src, dst, 16 * 16));
48}
49
50TEST_F(VideoProcessingTest, Variance) {
kwiberge065fcf2016-03-02 01:01:11 -080051 std::unique_ptr<DenoiserFilter> df_c(DenoiserFilter::Create(false));
52 std::unique_ptr<DenoiserFilter> df_sse_neon(DenoiserFilter::Create(true));
jackychen67e94fb2016-01-11 21:34:07 -080053 uint8_t src[16 * 16], dst[16 * 16];
54 uint32_t sum = 0, sse = 0, var;
55 for (int i = 0; i < 16; ++i) {
56 for (int j = 0; j < 16; ++j) {
57 src[i * 16 + j] = i * 16 + j;
58 }
59 }
60 // Compute the 16x8 variance of the 16x16 block.
61 for (int i = 0; i < 8; ++i) {
62 for (int j = 0; j < 16; ++j) {
63 sum += (i * 32 + j);
64 sse += (i * 32 + j) * (i * 32 + j);
65 }
66 }
67 var = sse - ((sum * sum) >> 7);
68 memset(dst, 0, 16 * 16);
69 EXPECT_EQ(var, df_c->Variance16x8(src, 16, dst, 16, &sse));
70 EXPECT_EQ(var, df_sse_neon->Variance16x8(src, 16, dst, 16, &sse));
71}
72
73TEST_F(VideoProcessingTest, MbDenoise) {
kwiberge065fcf2016-03-02 01:01:11 -080074 std::unique_ptr<DenoiserFilter> df_c(DenoiserFilter::Create(false));
75 std::unique_ptr<DenoiserFilter> df_sse_neon(DenoiserFilter::Create(true));
jackychen67e94fb2016-01-11 21:34:07 -080076 uint8_t running_src[16 * 16], src[16 * 16], dst[16 * 16], dst_ref[16 * 16];
77
78 // Test case: |diff| <= |3 + shift_inc1|
79 for (int i = 0; i < 16; ++i) {
80 for (int j = 0; j < 16; ++j) {
81 running_src[i * 16 + j] = i * 11 + j;
82 src[i * 16 + j] = i * 11 + j + 2;
83 dst_ref[i * 16 + j] = running_src[i * 16 + j];
84 }
85 }
86 memset(dst, 0, 16 * 16);
87 df_c->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1);
88 EXPECT_EQ(0, memcmp(dst, dst_ref, 16 * 16));
89
90 // Test case: |diff| >= |4 + shift_inc1|
91 for (int i = 0; i < 16; ++i) {
92 for (int j = 0; j < 16; ++j) {
93 running_src[i * 16 + j] = i * 11 + j;
94 src[i * 16 + j] = i * 11 + j + 5;
95 dst_ref[i * 16 + j] = src[i * 16 + j] - 2;
96 }
97 }
98 memset(dst, 0, 16 * 16);
99 df_c->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1);
100 EXPECT_EQ(0, memcmp(dst, dst_ref, 16 * 16));
101 memset(dst, 0, 16 * 16);
102 df_sse_neon->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1);
103 EXPECT_EQ(0, memcmp(dst, dst_ref, 16 * 16));
104
105 // Test case: |diff| >= 8
106 for (int i = 0; i < 16; ++i) {
107 for (int j = 0; j < 16; ++j) {
108 running_src[i * 16 + j] = i * 11 + j;
109 src[i * 16 + j] = i * 11 + j + 8;
110 dst_ref[i * 16 + j] = src[i * 16 + j] - 6;
111 }
112 }
113 memset(dst, 0, 16 * 16);
114 df_c->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1);
115 EXPECT_EQ(0, memcmp(dst, dst_ref, 16 * 16));
116 memset(dst, 0, 16 * 16);
117 df_sse_neon->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1);
118 EXPECT_EQ(0, memcmp(dst, dst_ref, 16 * 16));
119
120 // Test case: |diff| > 15
121 for (int i = 0; i < 16; ++i) {
122 for (int j = 0; j < 16; ++j) {
123 running_src[i * 16 + j] = i * 11 + j;
124 src[i * 16 + j] = i * 11 + j + 16;
125 }
126 }
127 memset(dst, 0, 16 * 16);
128 DenoiserDecision decision =
129 df_c->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1);
130 EXPECT_EQ(COPY_BLOCK, decision);
131 decision = df_sse_neon->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1);
132 EXPECT_EQ(COPY_BLOCK, decision);
133}
134
135TEST_F(VideoProcessingTest, Denoiser) {
136 // Create pure C denoiser.
137 VideoDenoiser denoiser_c(false);
138 // Create SSE or NEON denoiser.
139 VideoDenoiser denoiser_sse_neon(true);
140 VideoFrame denoised_frame_c;
141 VideoFrame denoised_frame_sse_neon;
142
kwiberge065fcf2016-03-02 01:01:11 -0800143 std::unique_ptr<uint8_t[]> video_buffer(new uint8_t[frame_length_]);
jackychen67e94fb2016-01-11 21:34:07 -0800144 while (fread(video_buffer.get(), 1, frame_length_, source_file_) ==
145 frame_length_) {
146 // Using ConvertToI420 to add stride to the image.
147 EXPECT_EQ(0, ConvertToI420(kI420, video_buffer.get(), 0, 0, width_, height_,
148 0, kVideoRotation_0, &video_frame_));
149
150 denoiser_c.DenoiseFrame(video_frame_, &denoised_frame_c);
151 denoiser_sse_neon.DenoiseFrame(video_frame_, &denoised_frame_sse_neon);
152
153 // Denoising results should be the same for C and SSE/NEON denoiser.
Niels Möller739fcb92016-02-29 13:11:45 +0100154 ASSERT_TRUE(test::FramesEqual(denoised_frame_c, denoised_frame_sse_neon));
jackychen67e94fb2016-01-11 21:34:07 -0800155 }
156 ASSERT_NE(0, feof(source_file_)) << "Error reading source file";
157}
158
159} // namespace webrtc