• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
13 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
14 #include "webrtc/modules/video_processing/include/video_processing.h"
15 #include "webrtc/modules/video_processing/test/video_processing_unittest.h"
16 #include "webrtc/modules/video_processing/video_denoiser.h"
17 
18 namespace webrtc {
19 
TEST_F(VideoProcessingTest,CopyMem)20 TEST_F(VideoProcessingTest, CopyMem) {
21   rtc::scoped_ptr<DenoiserFilter> df_c(DenoiserFilter::Create(false));
22   rtc::scoped_ptr<DenoiserFilter> df_sse_neon(DenoiserFilter::Create(true));
23   uint8_t src[16 * 16], dst[16 * 16];
24   for (int i = 0; i < 16; ++i) {
25     for (int j = 0; j < 16; ++j) {
26       src[i * 16 + j] = i * 16 + j;
27     }
28   }
29 
30   memset(dst, 0, 8 * 8);
31   df_c->CopyMem8x8(src, 8, dst, 8);
32   EXPECT_EQ(0, memcmp(src, dst, 8 * 8));
33 
34   memset(dst, 0, 16 * 16);
35   df_c->CopyMem16x16(src, 16, dst, 16);
36   EXPECT_EQ(0, memcmp(src, dst, 16 * 16));
37 
38   memset(dst, 0, 8 * 8);
39   df_sse_neon->CopyMem16x16(src, 8, dst, 8);
40   EXPECT_EQ(0, memcmp(src, dst, 8 * 8));
41 
42   memset(dst, 0, 16 * 16);
43   df_sse_neon->CopyMem16x16(src, 16, dst, 16);
44   EXPECT_EQ(0, memcmp(src, dst, 16 * 16));
45 }
46 
TEST_F(VideoProcessingTest,Variance)47 TEST_F(VideoProcessingTest, Variance) {
48   rtc::scoped_ptr<DenoiserFilter> df_c(DenoiserFilter::Create(false));
49   rtc::scoped_ptr<DenoiserFilter> df_sse_neon(DenoiserFilter::Create(true));
50   uint8_t src[16 * 16], dst[16 * 16];
51   uint32_t sum = 0, sse = 0, var;
52   for (int i = 0; i < 16; ++i) {
53     for (int j = 0; j < 16; ++j) {
54       src[i * 16 + j] = i * 16 + j;
55     }
56   }
57   // Compute the 16x8 variance of the 16x16 block.
58   for (int i = 0; i < 8; ++i) {
59     for (int j = 0; j < 16; ++j) {
60       sum += (i * 32 + j);
61       sse += (i * 32 + j) * (i * 32 + j);
62     }
63   }
64   var = sse - ((sum * sum) >> 7);
65   memset(dst, 0, 16 * 16);
66   EXPECT_EQ(var, df_c->Variance16x8(src, 16, dst, 16, &sse));
67   EXPECT_EQ(var, df_sse_neon->Variance16x8(src, 16, dst, 16, &sse));
68 }
69 
TEST_F(VideoProcessingTest,MbDenoise)70 TEST_F(VideoProcessingTest, MbDenoise) {
71   rtc::scoped_ptr<DenoiserFilter> df_c(DenoiserFilter::Create(false));
72   rtc::scoped_ptr<DenoiserFilter> df_sse_neon(DenoiserFilter::Create(true));
73   uint8_t running_src[16 * 16], src[16 * 16], dst[16 * 16], dst_ref[16 * 16];
74 
75   // Test case: |diff| <= |3 + shift_inc1|
76   for (int i = 0; i < 16; ++i) {
77     for (int j = 0; j < 16; ++j) {
78       running_src[i * 16 + j] = i * 11 + j;
79       src[i * 16 + j] = i * 11 + j + 2;
80       dst_ref[i * 16 + j] = running_src[i * 16 + j];
81     }
82   }
83   memset(dst, 0, 16 * 16);
84   df_c->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1);
85   EXPECT_EQ(0, memcmp(dst, dst_ref, 16 * 16));
86 
87   // Test case: |diff| >= |4 + shift_inc1|
88   for (int i = 0; i < 16; ++i) {
89     for (int j = 0; j < 16; ++j) {
90       running_src[i * 16 + j] = i * 11 + j;
91       src[i * 16 + j] = i * 11 + j + 5;
92       dst_ref[i * 16 + j] = src[i * 16 + j] - 2;
93     }
94   }
95   memset(dst, 0, 16 * 16);
96   df_c->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1);
97   EXPECT_EQ(0, memcmp(dst, dst_ref, 16 * 16));
98   memset(dst, 0, 16 * 16);
99   df_sse_neon->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1);
100   EXPECT_EQ(0, memcmp(dst, dst_ref, 16 * 16));
101 
102   // Test case: |diff| >= 8
103   for (int i = 0; i < 16; ++i) {
104     for (int j = 0; j < 16; ++j) {
105       running_src[i * 16 + j] = i * 11 + j;
106       src[i * 16 + j] = i * 11 + j + 8;
107       dst_ref[i * 16 + j] = src[i * 16 + j] - 6;
108     }
109   }
110   memset(dst, 0, 16 * 16);
111   df_c->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1);
112   EXPECT_EQ(0, memcmp(dst, dst_ref, 16 * 16));
113   memset(dst, 0, 16 * 16);
114   df_sse_neon->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1);
115   EXPECT_EQ(0, memcmp(dst, dst_ref, 16 * 16));
116 
117   // Test case: |diff| > 15
118   for (int i = 0; i < 16; ++i) {
119     for (int j = 0; j < 16; ++j) {
120       running_src[i * 16 + j] = i * 11 + j;
121       src[i * 16 + j] = i * 11 + j + 16;
122     }
123   }
124   memset(dst, 0, 16 * 16);
125   DenoiserDecision decision =
126       df_c->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1);
127   EXPECT_EQ(COPY_BLOCK, decision);
128   decision = df_sse_neon->MbDenoise(running_src, 16, dst, 16, src, 16, 0, 1);
129   EXPECT_EQ(COPY_BLOCK, decision);
130 }
131 
TEST_F(VideoProcessingTest,Denoiser)132 TEST_F(VideoProcessingTest, Denoiser) {
133   // Create pure C denoiser.
134   VideoDenoiser denoiser_c(false);
135   // Create SSE or NEON denoiser.
136   VideoDenoiser denoiser_sse_neon(true);
137   VideoFrame denoised_frame_c;
138   VideoFrame denoised_frame_sse_neon;
139 
140   rtc::scoped_ptr<uint8_t[]> video_buffer(new uint8_t[frame_length_]);
141   while (fread(video_buffer.get(), 1, frame_length_, source_file_) ==
142          frame_length_) {
143     // Using ConvertToI420 to add stride to the image.
144     EXPECT_EQ(0, ConvertToI420(kI420, video_buffer.get(), 0, 0, width_, height_,
145                                0, kVideoRotation_0, &video_frame_));
146 
147     denoiser_c.DenoiseFrame(video_frame_, &denoised_frame_c);
148     denoiser_sse_neon.DenoiseFrame(video_frame_, &denoised_frame_sse_neon);
149 
150     // Denoising results should be the same for C and SSE/NEON denoiser.
151     ASSERT_EQ(true, denoised_frame_c.EqualsFrame(denoised_frame_sse_neon));
152   }
153   ASSERT_NE(0, feof(source_file_)) << "Error reading source file";
154 }
155 
156 }  // namespace webrtc
157