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

Side by Side Diff: source/libvpx/vp9/encoder/vp9_denoiser.c

Issue 554673004: libvpx: Pull from upstream (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/libvpx/
Patch Set: Created 6 years, 3 months 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 | Annotate | Revision Log
« no previous file with comments | « source/libvpx/vp9/encoder/vp9_denoiser.h ('k') | source/libvpx/vp9/encoder/vp9_encodeframe.c » ('j') | 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) 2012 The WebM project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebM 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
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 71
72 static int total_adj_weak_thresh(BLOCK_SIZE bs, int increase_denoising) { 72 static int total_adj_weak_thresh(BLOCK_SIZE bs, int increase_denoising) {
73 return widths[bs] * heights[bs] * (increase_denoising ? 3 : 2); 73 return widths[bs] * heights[bs] * (increase_denoising ? 3 : 2);
74 } 74 }
75 75
76 static VP9_DENOISER_DECISION denoiser_filter(const uint8_t *sig, int sig_stride, 76 static VP9_DENOISER_DECISION denoiser_filter(const uint8_t *sig, int sig_stride,
77 const uint8_t *mc_avg, 77 const uint8_t *mc_avg,
78 int mc_avg_stride, 78 int mc_avg_stride,
79 uint8_t *avg, int avg_stride, 79 uint8_t *avg, int avg_stride,
80 int increase_denoising, 80 int increase_denoising,
81 BLOCK_SIZE bs) { 81 BLOCK_SIZE bs,
82 int motion_magnitude) {
82 int r, c; 83 int r, c;
83 const uint8_t *sig_start = sig; 84 const uint8_t *sig_start = sig;
84 const uint8_t *mc_avg_start = mc_avg; 85 const uint8_t *mc_avg_start = mc_avg;
85 uint8_t *avg_start = avg; 86 uint8_t *avg_start = avg;
86 int diff, adj, absdiff, delta; 87 int diff, adj, absdiff, delta;
87 int adj_val[] = {3, 4, 6}; 88 int adj_val[] = {3, 4, 6};
88 int total_adj = 0; 89 int total_adj = 0;
90 int shift_inc = 1;
91
92 /* If motion_magnitude is small, making the denoiser more aggressive by
93 * increasing the adjustment for each level. Add another increment for
94 * blocks that are labeled for increase denoising. */
95 if (motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD) {
96 if (increase_denoising) {
97 shift_inc = 2;
98 }
99 adj_val[0] += shift_inc;
100 adj_val[1] += shift_inc;
101 adj_val[2] += shift_inc;
102 }
89 103
90 // First attempt to apply a strong temporal denoising filter. 104 // First attempt to apply a strong temporal denoising filter.
91 for (r = 0; r < heights[bs]; ++r) { 105 for (r = 0; r < heights[bs]; ++r) {
92 for (c = 0; c < widths[bs]; ++c) { 106 for (c = 0; c < widths[bs]; ++c) {
93 diff = mc_avg[c] - sig[c]; 107 diff = mc_avg[c] - sig[c];
94 absdiff = abs(diff); 108 absdiff = abs(diff);
95 109
96 if (absdiff <= absdiff_thresh(bs, increase_denoising)) { 110 if (absdiff <= absdiff_thresh(bs, increase_denoising)) {
97 avg[c] = mc_avg[c]; 111 avg[c] = mc_avg[c];
98 total_adj += diff; 112 total_adj += diff;
(...skipping 24 matching lines...) Expand all
123 } 137 }
124 138
125 // If the strong filter did not modify the signal too much, we're all set. 139 // If the strong filter did not modify the signal too much, we're all set.
126 if (abs(total_adj) <= total_adj_strong_thresh(bs, increase_denoising)) { 140 if (abs(total_adj) <= total_adj_strong_thresh(bs, increase_denoising)) {
127 return FILTER_BLOCK; 141 return FILTER_BLOCK;
128 } 142 }
129 143
130 // Otherwise, we try to dampen the filter if the delta is not too high. 144 // Otherwise, we try to dampen the filter if the delta is not too high.
131 delta = ((abs(total_adj) - total_adj_strong_thresh(bs, increase_denoising)) 145 delta = ((abs(total_adj) - total_adj_strong_thresh(bs, increase_denoising))
132 >> 8) + 1; 146 >> 8) + 1;
133 if (delta > delta_thresh(bs, increase_denoising)) { 147
148 if (delta >= delta_thresh(bs, increase_denoising)) {
134 return COPY_BLOCK; 149 return COPY_BLOCK;
135 } 150 }
136 151
137 mc_avg = mc_avg_start; 152 mc_avg = mc_avg_start;
138 avg = avg_start; 153 avg = avg_start;
139 sig = sig_start; 154 sig = sig_start;
140 for (r = 0; r < heights[bs]; ++r) { 155 for (r = 0; r < heights[bs]; ++r) {
141 for (c = 0; c < widths[bs]; ++c) { 156 for (c = 0; c < widths[bs]; ++c) {
142 diff = mc_avg[c] - sig[c]; 157 diff = mc_avg[c] - sig[c];
143 adj = abs(diff); 158 adj = abs(diff);
144 if (adj > delta) { 159 if (adj > delta) {
145 adj = delta; 160 adj = delta;
146 } 161 }
147 if (diff > 0) { 162 if (diff > 0) {
163 // Diff positive means we made positive adjustment above
164 // (in first try/attempt), so now make negative adjustment to bring
165 // denoised signal down.
148 avg[c] = MAX(0, avg[c] - adj); 166 avg[c] = MAX(0, avg[c] - adj);
167 total_adj -= adj;
168 } else {
169 // Diff negative means we made negative adjustment above
170 // (in first try/attempt), so now make positive adjustment to bring
171 // denoised signal up.
172 avg[c] = MIN(UINT8_MAX, avg[c] + adj);
149 total_adj += adj; 173 total_adj += adj;
150 } else {
151 avg[c] = MIN(UINT8_MAX, avg[c] + adj);
152 total_adj -= adj;
153 } 174 }
154 } 175 }
155 sig += sig_stride; 176 sig += sig_stride;
156 avg += avg_stride; 177 avg += avg_stride;
157 mc_avg += mc_avg_stride; 178 mc_avg += mc_avg_stride;
158 } 179 }
159 180
160 // We can use the filter if it has been sufficiently dampened 181 // We can use the filter if it has been sufficiently dampened
161 if (abs(total_adj) <= total_adj_weak_thresh(bs, increase_denoising)) { 182 if (abs(total_adj) <= total_adj_weak_thresh(bs, increase_denoising)) {
162 return FILTER_BLOCK; 183 return FILTER_BLOCK;
(...skipping 15 matching lines...) Expand all
178 src += src_stride; 199 src += src_stride;
179 } 200 }
180 } 201 }
181 202
182 static VP9_DENOISER_DECISION perform_motion_compensation(VP9_DENOISER *denoiser, 203 static VP9_DENOISER_DECISION perform_motion_compensation(VP9_DENOISER *denoiser,
183 MACROBLOCK *mb, 204 MACROBLOCK *mb,
184 BLOCK_SIZE bs, 205 BLOCK_SIZE bs,
185 int increase_denoising, 206 int increase_denoising,
186 int mi_row, 207 int mi_row,
187 int mi_col, 208 int mi_col,
188 PICK_MODE_CONTEXT *ctx 209 PICK_MODE_CONTEXT *ctx,
210 int *motion_magnitude
189 ) { 211 ) {
190 int mv_col, mv_row; 212 int mv_col, mv_row;
191 int sse_diff = ctx->zeromv_sse - ctx->newmv_sse; 213 int sse_diff = ctx->zeromv_sse - ctx->newmv_sse;
192 MV_REFERENCE_FRAME frame; 214 MV_REFERENCE_FRAME frame;
193 MACROBLOCKD *filter_mbd = &mb->e_mbd; 215 MACROBLOCKD *filter_mbd = &mb->e_mbd;
194 MB_MODE_INFO *mbmi = &filter_mbd->mi[0]->mbmi; 216 MB_MODE_INFO *mbmi = &filter_mbd->mi[0]->mbmi;
195 217
196 MB_MODE_INFO saved_mbmi; 218 MB_MODE_INFO saved_mbmi;
197 int i, j; 219 int i, j;
198 struct buf_2d saved_dst[MAX_MB_PLANE]; 220 struct buf_2d saved_dst[MAX_MB_PLANE];
199 struct buf_2d saved_pre[MAX_MB_PLANE][2]; // 2 pre buffers 221 struct buf_2d saved_pre[MAX_MB_PLANE][2]; // 2 pre buffers
200 222
201 // We will restore these after motion compensation. 223 // We will restore these after motion compensation.
202 saved_mbmi = *mbmi; 224 saved_mbmi = *mbmi;
203 for (i = 0; i < MAX_MB_PLANE; ++i) { 225 for (i = 0; i < MAX_MB_PLANE; ++i) {
204 for (j = 0; j < 2; ++j) { 226 for (j = 0; j < 2; ++j) {
205 saved_pre[i][j] = filter_mbd->plane[i].pre[j]; 227 saved_pre[i][j] = filter_mbd->plane[i].pre[j];
206 } 228 }
207 saved_dst[i] = filter_mbd->plane[i].dst; 229 saved_dst[i] = filter_mbd->plane[i].dst;
208 } 230 }
209 231
210 mv_col = ctx->best_sse_mv.as_mv.col; 232 mv_col = ctx->best_sse_mv.as_mv.col;
211 mv_row = ctx->best_sse_mv.as_mv.row; 233 mv_row = ctx->best_sse_mv.as_mv.row;
212 234
235 *motion_magnitude = mv_row * mv_row + mv_col * mv_col;
236
213 frame = ctx->best_reference_frame; 237 frame = ctx->best_reference_frame;
214 238
215 // If the best reference frame uses inter-prediction and there is enough of a 239 // If the best reference frame uses inter-prediction and there is enough of a
216 // difference in sum-squared-error, use it. 240 // difference in sum-squared-error, use it.
217 if (frame != INTRA_FRAME && 241 if (frame != INTRA_FRAME &&
218 sse_diff > sse_diff_thresh(bs, increase_denoising, mv_row, mv_col)) { 242 sse_diff > sse_diff_thresh(bs, increase_denoising, mv_row, mv_col)) {
219 mbmi->ref_frame[0] = ctx->best_reference_frame; 243 mbmi->ref_frame[0] = ctx->best_reference_frame;
220 mbmi->mode = ctx->best_sse_inter_mode; 244 mbmi->mode = ctx->best_sse_inter_mode;
221 mbmi->mv[0] = ctx->best_sse_mv; 245 mbmi->mv[0] = ctx->best_sse_mv;
222 } else { 246 } else {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 if (mv_row * mv_row + mv_col * mv_col > 314 if (mv_row * mv_row + mv_col * mv_col >
291 8 * noise_motion_thresh(bs, increase_denoising)) { 315 8 * noise_motion_thresh(bs, increase_denoising)) {
292 return COPY_BLOCK; 316 return COPY_BLOCK;
293 } 317 }
294 return FILTER_BLOCK; 318 return FILTER_BLOCK;
295 } 319 }
296 320
297 void vp9_denoiser_denoise(VP9_DENOISER *denoiser, MACROBLOCK *mb, 321 void vp9_denoiser_denoise(VP9_DENOISER *denoiser, MACROBLOCK *mb,
298 int mi_row, int mi_col, BLOCK_SIZE bs, 322 int mi_row, int mi_col, BLOCK_SIZE bs,
299 PICK_MODE_CONTEXT *ctx) { 323 PICK_MODE_CONTEXT *ctx) {
324 int motion_magnitude = 0;
300 VP9_DENOISER_DECISION decision = FILTER_BLOCK; 325 VP9_DENOISER_DECISION decision = FILTER_BLOCK;
301 YV12_BUFFER_CONFIG avg = denoiser->running_avg_y[INTRA_FRAME]; 326 YV12_BUFFER_CONFIG avg = denoiser->running_avg_y[INTRA_FRAME];
302 YV12_BUFFER_CONFIG mc_avg = denoiser->mc_running_avg_y; 327 YV12_BUFFER_CONFIG mc_avg = denoiser->mc_running_avg_y;
303 uint8_t *avg_start = block_start(avg.y_buffer, avg.y_stride, mi_row, mi_col); 328 uint8_t *avg_start = block_start(avg.y_buffer, avg.y_stride, mi_row, mi_col);
304 uint8_t *mc_avg_start = block_start(mc_avg.y_buffer, mc_avg.y_stride, 329 uint8_t *mc_avg_start = block_start(mc_avg.y_buffer, mc_avg.y_stride,
305 mi_row, mi_col); 330 mi_row, mi_col);
306 struct buf_2d src = mb->plane[0].src; 331 struct buf_2d src = mb->plane[0].src;
307 332
308 decision = perform_motion_compensation(denoiser, mb, bs, 333 decision = perform_motion_compensation(denoiser, mb, bs,
309 denoiser->increase_denoising, 334 denoiser->increase_denoising,
310 mi_row, mi_col, ctx); 335 mi_row, mi_col, ctx,
336 &motion_magnitude);
311 337
312 if (decision == FILTER_BLOCK) { 338 if (decision == FILTER_BLOCK) {
313 decision = denoiser_filter(src.buf, src.stride, 339 decision = denoiser_filter(src.buf, src.stride,
314 mc_avg_start, mc_avg.y_stride, 340 mc_avg_start, mc_avg.y_stride,
315 avg_start, avg.y_stride, 341 avg_start, avg.y_stride,
316 0, bs); 342 0, bs, motion_magnitude);
317 } 343 }
318 344
319 if (decision == FILTER_BLOCK) { 345 if (decision == FILTER_BLOCK) {
320 copy_block(src.buf, src.stride, avg_start, avg.y_stride, bs); 346 copy_block(src.buf, src.stride, avg_start, avg.y_stride, bs);
321 } else { // COPY_BLOCK 347 } else { // COPY_BLOCK
322 copy_block(avg_start, avg.y_stride, src.buf, src.stride, bs); 348 copy_block(avg_start, avg.y_stride, src.buf, src.stride, bs);
323 } 349 }
324 } 350 }
325 351
326 static void copy_frame(YV12_BUFFER_CONFIG dest, const YV12_BUFFER_CONFIG src) { 352 static void copy_frame(YV12_BUFFER_CONFIG dest, const YV12_BUFFER_CONFIG src) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 denoiser->running_avg_y[INTRA_FRAME]); 389 denoiser->running_avg_y[INTRA_FRAME]);
364 } 390 }
365 } 391 }
366 } 392 }
367 393
368 void vp9_denoiser_reset_frame_stats(PICK_MODE_CONTEXT *ctx) { 394 void vp9_denoiser_reset_frame_stats(PICK_MODE_CONTEXT *ctx) {
369 ctx->zeromv_sse = UINT_MAX; 395 ctx->zeromv_sse = UINT_MAX;
370 ctx->newmv_sse = UINT_MAX; 396 ctx->newmv_sse = UINT_MAX;
371 } 397 }
372 398
373 void vp9_denoiser_update_frame_stats(VP9_DENOISER *denoiser, MB_MODE_INFO *mbmi, 399 void vp9_denoiser_update_frame_stats(MB_MODE_INFO *mbmi, unsigned int sse,
374 unsigned int sse, PREDICTION_MODE mode, 400 PREDICTION_MODE mode,
375 PICK_MODE_CONTEXT *ctx) { 401 PICK_MODE_CONTEXT *ctx) {
376 // TODO(tkopp): Use both MVs if possible 402 // TODO(tkopp): Use both MVs if possible
377 if (mbmi->mv[0].as_int == 0 && sse < ctx->zeromv_sse) { 403 if (mbmi->mv[0].as_int == 0 && sse < ctx->zeromv_sse) {
378 ctx->zeromv_sse = sse; 404 ctx->zeromv_sse = sse;
379 ctx->best_zeromv_reference_frame = mbmi->ref_frame[0]; 405 ctx->best_zeromv_reference_frame = mbmi->ref_frame[0];
380 } 406 }
381 407
382 if (mode == NEWMV) { 408 if (mode == NEWMV) {
383 ctx->newmv_sse = sse; 409 ctx->newmv_sse = sse;
384 ctx->best_sse_inter_mode = mode; 410 ctx->best_sse_inter_mode = mode;
385 ctx->best_sse_mv = mbmi->mv[0]; 411 ctx->best_sse_mv = mbmi->mv[0];
386 ctx->best_reference_frame = mbmi->ref_frame[0]; 412 ctx->best_reference_frame = mbmi->ref_frame[0];
387 } 413 }
388 } 414 }
389 415
390 int vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height, 416 int vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height,
391 int ssx, int ssy, int border) { 417 int ssx, int ssy,
418 #if CONFIG_VP9_HIGHBITDEPTH
419 int use_highbitdepth,
420 #endif
421 int border) {
392 int i, fail; 422 int i, fail;
393 assert(denoiser != NULL); 423 assert(denoiser != NULL);
394 424
395 for (i = 0; i < MAX_REF_FRAMES; ++i) { 425 for (i = 0; i < MAX_REF_FRAMES; ++i) {
396 fail = vp9_alloc_frame_buffer(&denoiser->running_avg_y[i], width, height, 426 fail = vp9_alloc_frame_buffer(&denoiser->running_avg_y[i], width, height,
397 ssx, ssy, border); 427 ssx, ssy,
428 #if CONFIG_VP9_HIGHBITDEPTH
429 use_highbitdepth,
430 #endif
431 border);
398 if (fail) { 432 if (fail) {
399 vp9_denoiser_free(denoiser); 433 vp9_denoiser_free(denoiser);
400 return 1; 434 return 1;
401 } 435 }
402 #ifdef OUTPUT_YUV_DENOISED 436 #ifdef OUTPUT_YUV_DENOISED
403 make_grayscale(&denoiser->running_avg_y[i]); 437 make_grayscale(&denoiser->running_avg_y[i]);
404 #endif 438 #endif
405 } 439 }
406 440
407 fail = vp9_alloc_frame_buffer(&denoiser->mc_running_avg_y, width, height, 441 fail = vp9_alloc_frame_buffer(&denoiser->mc_running_avg_y, width, height,
408 ssx, ssy, border); 442 ssx, ssy,
443 #if CONFIG_VP9_HIGHBITDEPTH
444 use_highbitdepth,
445 #endif
446 border);
409 if (fail) { 447 if (fail) {
410 vp9_denoiser_free(denoiser); 448 vp9_denoiser_free(denoiser);
411 return 1; 449 return 1;
412 } 450 }
413 #ifdef OUTPUT_YUV_DENOISED 451 #ifdef OUTPUT_YUV_DENOISED
414 make_grayscale(&denoiser->running_avg_y[i]); 452 make_grayscale(&denoiser->running_avg_y[i]);
415 #endif 453 #endif
416 denoiser->increase_denoising = 0; 454 denoiser->increase_denoising = 0;
417 455
418 return 0; 456 return 0;
(...skipping 25 matching lines...) Expand all
444 for (r = 0; r < yuv->uv_height / 2; ++r) { 482 for (r = 0; r < yuv->uv_height / 2; ++r) {
445 for (c = 0; c < yuv->uv_width / 2; ++c) { 483 for (c = 0; c < yuv->uv_width / 2; ++c) {
446 u[c] = UINT8_MAX / 2; 484 u[c] = UINT8_MAX / 2;
447 v[c] = UINT8_MAX / 2; 485 v[c] = UINT8_MAX / 2;
448 } 486 }
449 u += yuv->uv_stride + yuv->uv_width / 2; 487 u += yuv->uv_stride + yuv->uv_width / 2;
450 v += yuv->uv_stride + yuv->uv_width / 2; 488 v += yuv->uv_stride + yuv->uv_width / 2;
451 } 489 }
452 } 490 }
453 #endif 491 #endif
OLDNEW
« no previous file with comments | « source/libvpx/vp9/encoder/vp9_denoiser.h ('k') | source/libvpx/vp9/encoder/vp9_encodeframe.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698