Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(242)

Side by Side Diff: webrtc/modules/video_processing/video_denoiser.cc

Issue 2469763002: Refactor VideoDenoiser to use a buffer pool, replacing explicit double buffering. (Closed)
Patch Set: Rebase. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/modules/video_processing/video_denoiser.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" 11 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
12 #include "webrtc/modules/video_processing/video_denoiser.h" 12 #include "webrtc/modules/video_processing/video_denoiser.h"
13 #include "libyuv/planar_functions.h"
13 14
14 namespace webrtc { 15 namespace webrtc {
15 16
16 #if DISPLAY || DISPLAYNEON 17 #if DISPLAY || DISPLAYNEON
17 static void CopyMem8x8(const uint8_t* src, 18 static void CopyMem8x8(const uint8_t* src,
18 int src_stride, 19 int src_stride,
19 uint8_t* dst, 20 uint8_t* dst,
20 int dst_stride) { 21 int dst_stride) {
21 for (int i = 0; i < 8; i++) { 22 for (int i = 0; i < 8; i++) {
22 memcpy(dst, src, 8); 23 memcpy(dst, src, 8);
23 src += src_stride; 24 src += src_stride;
24 dst += dst_stride; 25 dst += dst_stride;
25 } 26 }
26 } 27 }
27 28
28 static void ShowRect(const std::unique_ptr<DenoiserFilter>& filter, 29 static void ShowRect(const std::unique_ptr<DenoiserFilter>& filter,
29 const std::unique_ptr<uint8_t[]>& d_status, 30 const std::unique_ptr<uint8_t[]>& d_status,
30 const std::unique_ptr<uint8_t[]>& moving_edge_red, 31 const std::unique_ptr<uint8_t[]>& moving_edge_red,
31 const std::unique_ptr<uint8_t[]>& x_density, 32 const std::unique_ptr<uint8_t[]>& x_density,
32 const std::unique_ptr<uint8_t[]>& y_density, 33 const std::unique_ptr<uint8_t[]>& y_density,
33 const uint8_t* u_src, 34 const uint8_t* u_src, int stride_u_src,
34 const uint8_t* v_src, 35 const uint8_t* v_src, int stride_v_src,
35 uint8_t* u_dst, 36 uint8_t* u_dst, int stride_u_dst,
36 uint8_t* v_dst, 37 uint8_t* v_dst, int stride_v_dst,
37 int mb_rows_, 38 int mb_rows_,
38 int mb_cols_, 39 int mb_cols_) {
39 int stride_u_,
40 int stride_v_) {
41 for (int mb_row = 0; mb_row < mb_rows_; ++mb_row) { 40 for (int mb_row = 0; mb_row < mb_rows_; ++mb_row) {
42 for (int mb_col = 0; mb_col < mb_cols_; ++mb_col) { 41 for (int mb_col = 0; mb_col < mb_cols_; ++mb_col) {
43 int mb_index = mb_row * mb_cols_ + mb_col; 42 int mb_index = mb_row * mb_cols_ + mb_col;
44 const uint8_t* mb_src_u = 43 const uint8_t* mb_src_u =
45 u_src + (mb_row << 3) * stride_u_ + (mb_col << 3); 44 u_src + (mb_row << 3) * stride_u_src + (mb_col << 3);
46 const uint8_t* mb_src_v = 45 const uint8_t* mb_src_v =
47 v_src + (mb_row << 3) * stride_v_ + (mb_col << 3); 46 v_src + (mb_row << 3) * stride_v_src + (mb_col << 3);
48 uint8_t* mb_dst_u = u_dst + (mb_row << 3) * stride_u_ + (mb_col << 3); 47 uint8_t* mb_dst_u = u_dst + (mb_row << 3) * stride_u_dst + (mb_col << 3);
49 uint8_t* mb_dst_v = v_dst + (mb_row << 3) * stride_v_ + (mb_col << 3); 48 uint8_t* mb_dst_v = v_dst + (mb_row << 3) * stride_v_dst + (mb_col << 3);
50 uint8_t uv_tmp[8 * 8]; 49 uint8_t uv_tmp[8 * 8];
51 memset(uv_tmp, 200, 8 * 8); 50 memset(uv_tmp, 200, 8 * 8);
52 if (d_status[mb_index] == 1) { 51 if (d_status[mb_index] == 1) {
53 // Paint to red. 52 // Paint to red.
54 CopyMem8x8(mb_src_u, stride_u_, mb_dst_u, stride_u_); 53 CopyMem8x8(mb_src_u, stride_u_src, mb_dst_u, stride_u_dst);
55 CopyMem8x8(uv_tmp, 8, mb_dst_v, stride_v_); 54 CopyMem8x8(uv_tmp, 8, mb_dst_v, stride_v_dst);
56 } else if (moving_edge_red[mb_row * mb_cols_ + mb_col] && 55 } else if (moving_edge_red[mb_row * mb_cols_ + mb_col] &&
57 x_density[mb_col] * y_density[mb_row]) { 56 x_density[mb_col] * y_density[mb_row]) {
58 // Paint to blue. 57 // Paint to blue.
59 CopyMem8x8(uv_tmp, 8, mb_dst_u, stride_u_); 58 CopyMem8x8(uv_tmp, 8, mb_dst_u, stride_u_dst);
60 CopyMem8x8(mb_src_v, stride_v_, mb_dst_v, stride_v_); 59 CopyMem8x8(mb_src_v, stride_v_src, mb_dst_v, stride_v_dst);
61 } else { 60 } else {
62 CopyMem8x8(mb_src_u, stride_u_, mb_dst_u, stride_u_); 61 CopyMem8x8(mb_src_u, stride_u_src, mb_dst_u, stride_u_dst);
63 CopyMem8x8(mb_src_v, stride_v_, mb_dst_v, stride_v_); 62 CopyMem8x8(mb_src_v, stride_v_src, mb_dst_v, stride_v_dst);
64 } 63 }
65 } 64 }
66 } 65 }
67 } 66 }
68 #endif 67 #endif
69 68
70 VideoDenoiser::VideoDenoiser(bool runtime_cpu_detection) 69 VideoDenoiser::VideoDenoiser(bool runtime_cpu_detection)
71 : width_(0), 70 : width_(0),
72 height_(0), 71 height_(0),
73 filter_(DenoiserFilter::Create(runtime_cpu_detection, &cpu_type_)), 72 filter_(DenoiserFilter::Create(runtime_cpu_detection, &cpu_type_)),
74 ne_(new NoiseEstimation()) {} 73 ne_(new NoiseEstimation()) {}
75 74
76 void VideoDenoiser::DenoiserReset( 75 void VideoDenoiser::DenoiserReset(rtc::scoped_refptr<VideoFrameBuffer> frame) {
77 const rtc::scoped_refptr<VideoFrameBuffer>& frame,
78 rtc::scoped_refptr<I420Buffer>* denoised_frame,
79 rtc::scoped_refptr<I420Buffer>* denoised_frame_prev) {
80 width_ = frame->width(); 76 width_ = frame->width();
81 height_ = frame->height(); 77 height_ = frame->height();
82 mb_cols_ = width_ >> 4; 78 mb_cols_ = width_ >> 4;
83 mb_rows_ = height_ >> 4; 79 mb_rows_ = height_ >> 4;
84 stride_y_ = frame->StrideY();
85 stride_u_ = frame->StrideU();
86 stride_v_ = frame->StrideV();
87
88 // Allocate an empty buffer for denoised_frame_prev.
89 *denoised_frame_prev = I420Buffer::Create(
90 width_, height_, stride_y_, stride_u_, stride_v_);
91 // Allocate and initialize denoised_frame with key frame.
92 *denoised_frame = I420Buffer::CopyKeepStride(frame);
93 80
94 // Init noise estimator and allocate buffers. 81 // Init noise estimator and allocate buffers.
95 ne_->Init(width_, height_, cpu_type_); 82 ne_->Init(width_, height_, cpu_type_);
96 moving_edge_.reset(new uint8_t[mb_cols_ * mb_rows_]); 83 moving_edge_.reset(new uint8_t[mb_cols_ * mb_rows_]);
97 mb_filter_decision_.reset(new DenoiserDecision[mb_cols_ * mb_rows_]); 84 mb_filter_decision_.reset(new DenoiserDecision[mb_cols_ * mb_rows_]);
98 x_density_.reset(new uint8_t[mb_cols_]); 85 x_density_.reset(new uint8_t[mb_cols_]);
99 y_density_.reset(new uint8_t[mb_rows_]); 86 y_density_.reset(new uint8_t[mb_rows_]);
100 moving_object_.reset(new uint8_t[mb_cols_ * mb_rows_]); 87 moving_object_.reset(new uint8_t[mb_cols_ * mb_rows_]);
101 } 88 }
102 89
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 bool ret = false; 156 bool ret = false;
170 int mb_index = mb_row * mb_cols_ + mb_col; 157 int mb_index = mb_row * mb_cols_ + mb_col;
171 if (!mb_row || !mb_col || mb_row == mb_rows_ - 1 || mb_col == mb_cols_ - 1) 158 if (!mb_row || !mb_col || mb_row == mb_rows_ - 1 || mb_col == mb_cols_ - 1)
172 ret = false; 159 ret = false;
173 else 160 else
174 ret = d_status[mb_index + 1] || d_status[mb_index - 1] || 161 ret = d_status[mb_index + 1] || d_status[mb_index - 1] ||
175 d_status[mb_index + mb_cols_] || d_status[mb_index - mb_cols_]; 162 d_status[mb_index + mb_cols_] || d_status[mb_index - mb_cols_];
176 return ret; 163 return ret;
177 } 164 }
178 165
179 void VideoDenoiser::CopySrcOnMOB(const uint8_t* y_src, uint8_t* y_dst) { 166 void VideoDenoiser::CopySrcOnMOB(const uint8_t* y_src,
167 int stride_src,
168 uint8_t* y_dst,
169 int stride_dst) {
180 // Loop over to copy src block if the block is marked as moving object block 170 // Loop over to copy src block if the block is marked as moving object block
181 // or if the block may cause trailing artifacts. 171 // or if the block may cause trailing artifacts.
182 for (int mb_row = 0; mb_row < mb_rows_; ++mb_row) { 172 for (int mb_row = 0; mb_row < mb_rows_; ++mb_row) {
183 const int mb_index_base = mb_row * mb_cols_; 173 const int mb_index_base = mb_row * mb_cols_;
184 const int offset_base = (mb_row << 4) * stride_y_; 174 const uint8_t* mb_src_base = y_src + (mb_row << 4) * stride_src;
185 const uint8_t* mb_src_base = y_src + offset_base; 175 uint8_t* mb_dst_base = y_dst + (mb_row << 4) * stride_dst;
186 uint8_t* mb_dst_base = y_dst + offset_base;
187 for (int mb_col = 0; mb_col < mb_cols_; ++mb_col) { 176 for (int mb_col = 0; mb_col < mb_cols_; ++mb_col) {
188 const int mb_index = mb_index_base + mb_col; 177 const int mb_index = mb_index_base + mb_col;
189 const uint32_t offset_col = mb_col << 4; 178 const uint32_t offset_col = mb_col << 4;
190 const uint8_t* mb_src = mb_src_base + offset_col; 179 const uint8_t* mb_src = mb_src_base + offset_col;
191 uint8_t* mb_dst = mb_dst_base + offset_col; 180 uint8_t* mb_dst = mb_dst_base + offset_col;
192 // Check if the block is a moving object block or may cause a trailing 181 // Check if the block is a moving object block or may cause a trailing
193 // artifacts. 182 // artifacts.
194 if (mb_filter_decision_[mb_index] != FILTER_BLOCK || 183 if (mb_filter_decision_[mb_index] != FILTER_BLOCK ||
195 IsTrailingBlock(moving_edge_, mb_row, mb_col) || 184 IsTrailingBlock(moving_edge_, mb_row, mb_col) ||
196 (x_density_[mb_col] * y_density_[mb_row] && 185 (x_density_[mb_col] * y_density_[mb_row] &&
197 moving_object_[mb_row * mb_cols_ + mb_col])) { 186 moving_object_[mb_row * mb_cols_ + mb_col])) {
198 // Copy y source. 187 // Copy y source.
199 filter_->CopyMem16x16(mb_src, stride_y_, mb_dst, stride_y_); 188 filter_->CopyMem16x16(mb_src, stride_src, mb_dst, stride_dst);
200 } 189 }
201 } 190 }
202 } 191 }
203 } 192 }
204 193
205 void VideoDenoiser::CopyLumaOnMargin(const uint8_t* y_src, uint8_t* y_dst) { 194 void VideoDenoiser::CopyLumaOnMargin(const uint8_t* y_src,
206 if ((mb_rows_ << 4) != height_) { 195 int stride_src,
207 const uint8_t* margin_y_src = y_src + (mb_rows_ << 4) * stride_y_; 196 uint8_t* y_dst,
208 uint8_t* margin_y_dst = y_dst + (mb_rows_ << 4) * stride_y_; 197 int stride_dst) {
209 memcpy(margin_y_dst, margin_y_src, (height_ - (mb_rows_ << 4)) * stride_y_); 198 int height_margin = height_ - (mb_rows_ << 4);
199 if (height_margin > 0) {
200 const uint8_t* margin_y_src = y_src + (mb_rows_ << 4) * stride_src;
201 uint8_t* margin_y_dst = y_dst + (mb_rows_ << 4) * stride_dst;
202 libyuv::CopyPlane(margin_y_src, stride_src, margin_y_dst, stride_dst,
203 width_, height_margin);
210 } 204 }
211 if ((mb_cols_ << 4) != width_) { 205 int width_margin = width_ - (mb_cols_ << 4);
206 if (width_margin > 0) {
212 const uint8_t* margin_y_src = y_src + (mb_cols_ << 4); 207 const uint8_t* margin_y_src = y_src + (mb_cols_ << 4);
213 uint8_t* margin_y_dst = y_dst + (mb_cols_ << 4); 208 uint8_t* margin_y_dst = y_dst + (mb_cols_ << 4);
214 for (int i = 0; i < height_; ++i) { 209 libyuv::CopyPlane(margin_y_src, stride_src, margin_y_dst, stride_dst,
215 for (int j = mb_cols_ << 4; j < width_; ++j) { 210 width_ - (mb_cols_ << 4), mb_rows_ << 4);
216 margin_y_dst[i * stride_y_ + j] = margin_y_src[i * stride_y_ + j];
217 }
218 }
219 } 211 }
220 } 212 }
221 213
222 void VideoDenoiser::DenoiseFrame( 214 rtc::scoped_refptr<VideoFrameBuffer> VideoDenoiser::DenoiseFrame(
223 const rtc::scoped_refptr<VideoFrameBuffer>& frame, 215 rtc::scoped_refptr<VideoFrameBuffer> frame,
224 rtc::scoped_refptr<I420Buffer>* denoised_frame,
225 rtc::scoped_refptr<I420Buffer>* denoised_frame_prev,
226 bool noise_estimation_enabled) { 216 bool noise_estimation_enabled) {
227 // If previous width and height are different from current frame's, need to 217 // If previous width and height are different from current frame's, need to
228 // reallocate the buffers and no denoising for the current frame. 218 // reallocate the buffers and no denoising for the current frame.
229 if (width_ != frame->width() || height_ != frame->height()) { 219 if (!prev_buffer_ || width_ != frame->width() || height_ != frame->height()) {
230 DenoiserReset(frame, denoised_frame, denoised_frame_prev); 220 DenoiserReset(frame);
231 return; 221 prev_buffer_ = frame;
222 return frame;
232 } 223 }
233 224
234 // Set buffer pointers. 225 // Set buffer pointers.
235 const uint8_t* y_src = frame->DataY(); 226 const uint8_t* y_src = frame->DataY();
236 const uint8_t* u_src = frame->DataU(); 227 int stride_y_src = frame->StrideY();
237 const uint8_t* v_src = frame->DataV(); 228 rtc::scoped_refptr<I420Buffer> dst =
238 uint8_t* y_dst = (*denoised_frame)->MutableDataY(); 229 buffer_pool_.CreateBuffer(width_, height_);
239 uint8_t* u_dst = (*denoised_frame)->MutableDataU(); 230
240 uint8_t* v_dst = (*denoised_frame)->MutableDataV(); 231 uint8_t* y_dst = dst->MutableDataY();
241 uint8_t* y_dst_prev = (*denoised_frame_prev)->MutableDataY(); 232 int stride_y_dst = dst->StrideY();
233
234 const uint8_t* y_dst_prev = prev_buffer_->DataY();
235 int stride_prev = prev_buffer_->StrideY();
236
242 memset(x_density_.get(), 0, mb_cols_); 237 memset(x_density_.get(), 0, mb_cols_);
243 memset(y_density_.get(), 0, mb_rows_); 238 memset(y_density_.get(), 0, mb_rows_);
244 memset(moving_object_.get(), 1, mb_cols_ * mb_rows_); 239 memset(moving_object_.get(), 1, mb_cols_ * mb_rows_);
245 240
246 uint8_t noise_level = noise_estimation_enabled ? ne_->GetNoiseLevel() : 0; 241 uint8_t noise_level = noise_estimation_enabled ? ne_->GetNoiseLevel() : 0;
247 int thr_var_base = 16 * 16 * 2; 242 int thr_var_base = 16 * 16 * 2;
248 // Loop over blocks to accumulate/extract noise level and update x/y_density 243 // Loop over blocks to accumulate/extract noise level and update x/y_density
249 // factors for moving object detection. 244 // factors for moving object detection.
250 for (int mb_row = 0; mb_row < mb_rows_; ++mb_row) { 245 for (int mb_row = 0; mb_row < mb_rows_; ++mb_row) {
251 const int mb_index_base = mb_row * mb_cols_; 246 const int mb_index_base = mb_row * mb_cols_;
252 const int offset_base = (mb_row << 4) * stride_y_; 247 const uint8_t* mb_src_base = y_src + (mb_row << 4) * stride_y_src;
253 const uint8_t* mb_src_base = y_src + offset_base; 248 uint8_t* mb_dst_base = y_dst + (mb_row << 4) * stride_y_dst;
254 uint8_t* mb_dst_base = y_dst + offset_base; 249 const uint8_t* mb_dst_prev_base = y_dst_prev + (mb_row << 4) * stride_prev;
255 uint8_t* mb_dst_prev_base = y_dst_prev + offset_base;
256 for (int mb_col = 0; mb_col < mb_cols_; ++mb_col) { 250 for (int mb_col = 0; mb_col < mb_cols_; ++mb_col) {
257 const int mb_index = mb_index_base + mb_col; 251 const int mb_index = mb_index_base + mb_col;
258 const bool ne_enable = (mb_index % NOISE_SUBSAMPLE_INTERVAL == 0); 252 const bool ne_enable = (mb_index % NOISE_SUBSAMPLE_INTERVAL == 0);
259 const int pos_factor = PositionCheck(mb_row, mb_col, noise_level); 253 const int pos_factor = PositionCheck(mb_row, mb_col, noise_level);
260 const uint32_t thr_var_adp = thr_var_base * pos_factor; 254 const uint32_t thr_var_adp = thr_var_base * pos_factor;
261 const uint32_t offset_col = mb_col << 4; 255 const uint32_t offset_col = mb_col << 4;
262 const uint8_t* mb_src = mb_src_base + offset_col; 256 const uint8_t* mb_src = mb_src_base + offset_col;
263 uint8_t* mb_dst = mb_dst_base + offset_col; 257 uint8_t* mb_dst = mb_dst_base + offset_col;
264 uint8_t* mb_dst_prev = mb_dst_prev_base + offset_col; 258 const uint8_t* mb_dst_prev = mb_dst_prev_base + offset_col;
265 259
266 // TODO(jackychen): Need SSE2/NEON opt. 260 // TODO(jackychen): Need SSE2/NEON opt.
267 int luma = 0; 261 int luma = 0;
268 if (ne_enable) { 262 if (ne_enable) {
269 for (int i = 4; i < 12; ++i) { 263 for (int i = 4; i < 12; ++i) {
270 for (int j = 4; j < 12; ++j) { 264 for (int j = 4; j < 12; ++j) {
271 luma += mb_src[i * stride_y_ + j]; 265 luma += mb_src[i * stride_y_src + j];
272 } 266 }
273 } 267 }
274 } 268 }
275 269
276 // Get the filtered block and filter_decision. 270 // Get the filtered block and filter_decision.
277 mb_filter_decision_[mb_index] = 271 mb_filter_decision_[mb_index] =
278 filter_->MbDenoise(mb_dst_prev, stride_y_, mb_dst, stride_y_, mb_src, 272 filter_->MbDenoise(mb_dst_prev, stride_prev, mb_dst, stride_y_dst,
279 stride_y_, 0, noise_level); 273 mb_src, stride_y_src, 0, noise_level);
280 274
281 // If filter decision is FILTER_BLOCK, no need to check moving edge. 275 // If filter decision is FILTER_BLOCK, no need to check moving edge.
282 // It is unlikely for a moving edge block to be filtered in current 276 // It is unlikely for a moving edge block to be filtered in current
283 // setting. 277 // setting.
284 if (mb_filter_decision_[mb_index] == FILTER_BLOCK) { 278 if (mb_filter_decision_[mb_index] == FILTER_BLOCK) {
285 uint32_t sse_t = 0; 279 uint32_t sse_t = 0;
286 if (ne_enable) { 280 if (ne_enable) {
287 // The variance used in noise estimation is based on the src block in 281 // The variance used in noise estimation is based on the src block in
288 // time t (mb_src) and filtered block in time t-1 (mb_dist_prev). 282 // time t (mb_src) and filtered block in time t-1 (mb_dist_prev).
289 uint32_t noise_var = filter_->Variance16x8(mb_dst_prev, stride_y_, 283 uint32_t noise_var = filter_->Variance16x8(
290 mb_src, stride_y_, &sse_t); 284 mb_dst_prev, stride_y_dst, mb_src, stride_y_src, &sse_t);
291 ne_->GetNoise(mb_index, noise_var, luma); 285 ne_->GetNoise(mb_index, noise_var, luma);
292 } 286 }
293 moving_edge_[mb_index] = 0; // Not a moving edge block. 287 moving_edge_[mb_index] = 0; // Not a moving edge block.
294 } else { 288 } else {
295 uint32_t sse_t = 0; 289 uint32_t sse_t = 0;
296 // The variance used in MOD is based on the filtered blocks in time 290 // The variance used in MOD is based on the filtered blocks in time
297 // T (mb_dst) and T-1 (mb_dst_prev). 291 // T (mb_dst) and T-1 (mb_dst_prev).
298 uint32_t noise_var = filter_->Variance16x8(mb_dst_prev, stride_y_, 292 uint32_t noise_var = filter_->Variance16x8(
299 mb_dst, stride_y_, &sse_t); 293 mb_dst_prev, stride_prev, mb_dst, stride_y_dst, &sse_t);
300 if (noise_var > thr_var_adp) { // Moving edge checking. 294 if (noise_var > thr_var_adp) { // Moving edge checking.
301 if (ne_enable) { 295 if (ne_enable) {
302 ne_->ResetConsecLowVar(mb_index); 296 ne_->ResetConsecLowVar(mb_index);
303 } 297 }
304 moving_edge_[mb_index] = 1; // Mark as moving edge block. 298 moving_edge_[mb_index] = 1; // Mark as moving edge block.
305 x_density_[mb_col] += (pos_factor < 3); 299 x_density_[mb_col] += (pos_factor < 3);
306 y_density_[mb_row] += (pos_factor < 3); 300 y_density_[mb_row] += (pos_factor < 3);
307 } else { 301 } else {
308 moving_edge_[mb_index] = 0; 302 moving_edge_[mb_index] = 0;
309 if (ne_enable) { 303 if (ne_enable) {
310 // The variance used in noise estimation is based on the src block 304 // The variance used in noise estimation is based on the src block
311 // in time t (mb_src) and filtered block in time t-1 (mb_dist_prev). 305 // in time t (mb_src) and filtered block in time t-1 (mb_dist_prev).
312 uint32_t noise_var = filter_->Variance16x8( 306 uint32_t noise_var = filter_->Variance16x8(
313 mb_dst_prev, stride_y_, mb_src, stride_y_, &sse_t); 307 mb_dst_prev, stride_prev, mb_src, stride_y_src, &sse_t);
314 ne_->GetNoise(mb_index, noise_var, luma); 308 ne_->GetNoise(mb_index, noise_var, luma);
315 } 309 }
316 } 310 }
317 } 311 }
318 } // End of for loop 312 } // End of for loop
319 } // End of for loop 313 } // End of for loop
320 314
321 ReduceFalseDetection(moving_edge_, &moving_object_, noise_level); 315 ReduceFalseDetection(moving_edge_, &moving_object_, noise_level);
322 316
323 CopySrcOnMOB(y_src, y_dst); 317 CopySrcOnMOB(y_src, stride_y_src, y_dst, stride_y_dst);
324 318
325 // When frame width/height not divisible by 16, copy the margin to 319 // When frame width/height not divisible by 16, copy the margin to
326 // denoised_frame. 320 // denoised_frame.
327 if ((mb_rows_ << 4) != height_ || (mb_cols_ << 4) != width_) 321 if ((mb_rows_ << 4) != height_ || (mb_cols_ << 4) != width_)
328 CopyLumaOnMargin(y_src, y_dst); 322 CopyLumaOnMargin(y_src, stride_y_src, y_dst, stride_y_dst);
329 323
330 // TODO(jackychen): Need SSE2/NEON opt.
331 // Copy u/v planes. 324 // Copy u/v planes.
332 memcpy(u_dst, u_src, (height_ >> 1) * stride_u_); 325 libyuv::CopyPlane(frame->DataU(), frame->StrideU(),
333 memcpy(v_dst, v_src, (height_ >> 1) * stride_v_); 326 dst->MutableDataU(), dst->StrideU(),
327 (width_ + 1) >> 1, (height_ + 1) >> 1);
328 libyuv::CopyPlane(frame->DataV(), frame->StrideV(),
329 dst->MutableDataV(), dst->StrideV(),
330 (width_ + 1) >> 1, (height_ + 1) >> 1);
334 331
335 #if DISPLAY || DISPLAYNEON 332 #if DISPLAY || DISPLAYNEON
336 // Show rectangular region 333 // Show rectangular region
337 ShowRect(filter_, moving_edge_, moving_object_, x_density_, y_density_, u_src, 334 ShowRect(filter_, moving_edge_, moving_object_, x_density_, y_density_,
338 v_src, u_dst, v_dst, mb_rows_, mb_cols_, stride_u_, stride_v_); 335 frame->DataU(), frame->StrideU(), frame->DataV(), frame->StrideV(),
336 dst->MutableDataU(), dst->StrideU(),
337 dst->MutableDataV(), dst->StrideV(),
338 mb_rows_, mb_cols_);
339 #endif 339 #endif
340 prev_buffer_ = dst;
341 return dst;
340 } 342 }
341 343
342 } // namespace webrtc 344 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/video_processing/video_denoiser.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698