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

Side by Side Diff: source/libvpx/vp8/encoder/denoising.c

Issue 341293003: libvpx: Pull from upstream (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/libvpx/
Patch Set: Created 6 years, 6 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/vp8/encoder/denoising.h ('k') | source/libvpx/vp8/encoder/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 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 } 129 }
130 130
131 /* Update pointers for next iteration. */ 131 /* Update pointers for next iteration. */
132 sig += sig_stride; 132 sig += sig_stride;
133 mc_running_avg_y += mc_avg_y_stride; 133 mc_running_avg_y += mc_avg_y_stride;
134 running_avg_y += avg_y_stride; 134 running_avg_y += avg_y_stride;
135 } 135 }
136 136
137 sum_diff_thresh= SUM_DIFF_THRESHOLD; 137 sum_diff_thresh= SUM_DIFF_THRESHOLD;
138 if (increase_denoising) sum_diff_thresh = SUM_DIFF_THRESHOLD_HIGH; 138 if (increase_denoising) sum_diff_thresh = SUM_DIFF_THRESHOLD_HIGH;
139 if (abs(sum_diff) > sum_diff_thresh) 139 if (abs(sum_diff) > sum_diff_thresh) {
140 // Before returning to copy the block (i.e., apply no denoising), check
141 // if we can still apply some (weaker) temporal filtering to this block,
142 // that would otherwise not be denoised at all. Simplest is to apply
143 // an additional adjustment to running_avg_y to bring it closer to sig.
144 // The adjustment is capped by a maximum delta, and chosen such that
145 // in most cases the resulting sum_diff will be within the
146 // accceptable range given by sum_diff_thresh.
147
148 // The delta is set by the excess of absolute pixel diff over threshold.
149 int delta = ((abs(sum_diff) - sum_diff_thresh) >> 8) + 1;
150 // Only apply the adjustment for max delta up to 3.
151 if (delta < 4) {
152 sig -= sig_stride * 16;
153 mc_running_avg_y -= mc_avg_y_stride * 16;
154 running_avg_y -= avg_y_stride * 16;
155 for (r = 0; r < 16; ++r) {
156 for (c = 0; c < 16; ++c) {
157 int diff = mc_running_avg_y[c] - sig[c];
158 int adjustment = abs(diff);
159 if (adjustment > delta)
160 adjustment = delta;
161 if (diff > 0) {
162 // Bring denoised signal down.
163 if (running_avg_y[c] - adjustment < 0)
164 running_avg_y[c] = 0;
165 else
166 running_avg_y[c] = running_avg_y[c] - adjustment;
167 sum_diff -= adjustment;
168 } else if (diff < 0) {
169 // Bring denoised signal up.
170 if (running_avg_y[c] + adjustment > 255)
171 running_avg_y[c] = 255;
172 else
173 running_avg_y[c] = running_avg_y[c] + adjustment;
174 sum_diff += adjustment;
175 }
176 }
177 // TODO(marpan): Check here if abs(sum_diff) has gone below the
178 // threshold sum_diff_thresh, and if so, we can exit the row loop.
179 sig += sig_stride;
180 mc_running_avg_y += mc_avg_y_stride;
181 running_avg_y += avg_y_stride;
182 }
183 if (abs(sum_diff) > sum_diff_thresh)
184 return COPY_BLOCK;
185 } else {
140 return COPY_BLOCK; 186 return COPY_BLOCK;
187 }
188 }
141 189
142 vp8_copy_mem16x16(running_avg_y_start, avg_y_stride, sig_start, sig_stride); 190 vp8_copy_mem16x16(running_avg_y_start, avg_y_stride, sig_start, sig_stride);
143 return FILTER_BLOCK; 191 return FILTER_BLOCK;
144 } 192 }
145 193
146 int vp8_denoiser_allocate(VP8_DENOISER *denoiser, int width, int height) 194 int vp8_denoiser_allocate(VP8_DENOISER *denoiser, int width, int height,
195 int num_mb_rows, int num_mb_cols)
147 { 196 {
148 int i; 197 int i;
149 assert(denoiser); 198 assert(denoiser);
199 denoiser->num_mb_cols = num_mb_cols;
150 200
151 for (i = 0; i < MAX_REF_FRAMES; i++) 201 for (i = 0; i < MAX_REF_FRAMES; i++)
152 { 202 {
153 denoiser->yv12_running_avg[i].flags = 0; 203 denoiser->yv12_running_avg[i].flags = 0;
154 204
155 if (vp8_yv12_alloc_frame_buffer(&(denoiser->yv12_running_avg[i]), width, 205 if (vp8_yv12_alloc_frame_buffer(&(denoiser->yv12_running_avg[i]), width,
156 height, VP8BORDERINPIXELS) 206 height, VP8BORDERINPIXELS)
157 < 0) 207 < 0)
158 { 208 {
159 vp8_denoiser_free(denoiser); 209 vp8_denoiser_free(denoiser);
160 return 1; 210 return 1;
161 } 211 }
162 vpx_memset(denoiser->yv12_running_avg[i].buffer_alloc, 0, 212 vpx_memset(denoiser->yv12_running_avg[i].buffer_alloc, 0,
163 denoiser->yv12_running_avg[i].frame_size); 213 denoiser->yv12_running_avg[i].frame_size);
164 214
165 } 215 }
166 denoiser->yv12_mc_running_avg.flags = 0; 216 denoiser->yv12_mc_running_avg.flags = 0;
167 217
168 if (vp8_yv12_alloc_frame_buffer(&(denoiser->yv12_mc_running_avg), width, 218 if (vp8_yv12_alloc_frame_buffer(&(denoiser->yv12_mc_running_avg), width,
169 height, VP8BORDERINPIXELS) < 0) 219 height, VP8BORDERINPIXELS) < 0)
170 { 220 {
171 vp8_denoiser_free(denoiser); 221 vp8_denoiser_free(denoiser);
172 return 1; 222 return 1;
173 } 223 }
174 224
175 vpx_memset(denoiser->yv12_mc_running_avg.buffer_alloc, 0, 225 vpx_memset(denoiser->yv12_mc_running_avg.buffer_alloc, 0,
176 denoiser->yv12_mc_running_avg.frame_size); 226 denoiser->yv12_mc_running_avg.frame_size);
227
228 denoiser->denoise_state = vpx_calloc((num_mb_rows * num_mb_cols), 1);
229 vpx_memset(denoiser->denoise_state, 0, (num_mb_rows * num_mb_cols));
230
177 return 0; 231 return 0;
178 } 232 }
179 233
180 void vp8_denoiser_free(VP8_DENOISER *denoiser) 234 void vp8_denoiser_free(VP8_DENOISER *denoiser)
181 { 235 {
182 int i; 236 int i;
183 assert(denoiser); 237 assert(denoiser);
184 238
185 for (i = 0; i < MAX_REF_FRAMES ; i++) 239 for (i = 0; i < MAX_REF_FRAMES ; i++)
186 { 240 {
187 vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_running_avg[i]); 241 vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_running_avg[i]);
188 } 242 }
189 vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_mc_running_avg); 243 vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_mc_running_avg);
190 } 244 }
191 245
192 246
193 void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser, 247 void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser,
194 MACROBLOCK *x, 248 MACROBLOCK *x,
195 unsigned int best_sse, 249 unsigned int best_sse,
196 unsigned int zero_mv_sse, 250 unsigned int zero_mv_sse,
197 int recon_yoffset, 251 int recon_yoffset,
198 int recon_uvoffset) 252 int recon_uvoffset,
253 loop_filter_info_n *lfi_n,
254 int mb_row,
255 int mb_col,
256 int block_index)
199 { 257 {
200 int mv_row; 258 int mv_row;
201 int mv_col; 259 int mv_col;
202 unsigned int motion_magnitude2; 260 unsigned int motion_magnitude2;
203 unsigned int sse_thresh; 261 unsigned int sse_thresh;
262 int sse_diff_thresh = 0;
263 // Spatial loop filter: only applied selectively based on
264 // temporal filter state of block relative to top/left neighbors.
265 int apply_spatial_loop_filter = 1;
204 MV_REFERENCE_FRAME frame = x->best_reference_frame; 266 MV_REFERENCE_FRAME frame = x->best_reference_frame;
205 MV_REFERENCE_FRAME zero_frame = x->best_zeromv_reference_frame; 267 MV_REFERENCE_FRAME zero_frame = x->best_zeromv_reference_frame;
206 268
207 enum vp8_denoiser_decision decision = FILTER_BLOCK; 269 enum vp8_denoiser_decision decision = FILTER_BLOCK;
208 270
209 if (zero_frame) 271 if (zero_frame)
210 { 272 {
211 YV12_BUFFER_CONFIG *src = &denoiser->yv12_running_avg[frame]; 273 YV12_BUFFER_CONFIG *src = &denoiser->yv12_running_avg[frame];
212 YV12_BUFFER_CONFIG *dst = &denoiser->yv12_mc_running_avg; 274 YV12_BUFFER_CONFIG *dst = &denoiser->yv12_mc_running_avg;
213 YV12_BUFFER_CONFIG saved_pre,saved_dst; 275 YV12_BUFFER_CONFIG saved_pre,saved_dst;
214 MB_MODE_INFO saved_mbmi; 276 MB_MODE_INFO saved_mbmi;
215 MACROBLOCKD *filter_xd = &x->e_mbd; 277 MACROBLOCKD *filter_xd = &x->e_mbd;
216 MB_MODE_INFO *mbmi = &filter_xd->mode_info_context->mbmi; 278 MB_MODE_INFO *mbmi = &filter_xd->mode_info_context->mbmi;
217 int sse_diff = zero_mv_sse - best_sse; 279 int sse_diff = 0;
280 // Bias on zero motion vector sse.
281 int zero_bias = 95;
282 zero_mv_sse = (unsigned int)((int64_t)zero_mv_sse * zero_bias / 100);
283 sse_diff = zero_mv_sse - best_sse;
218 284
219 saved_mbmi = *mbmi; 285 saved_mbmi = *mbmi;
220 286
221 /* Use the best MV for the compensation. */ 287 /* Use the best MV for the compensation. */
222 mbmi->ref_frame = x->best_reference_frame; 288 mbmi->ref_frame = x->best_reference_frame;
223 mbmi->mode = x->best_sse_inter_mode; 289 mbmi->mode = x->best_sse_inter_mode;
224 mbmi->mv = x->best_sse_mv; 290 mbmi->mv = x->best_sse_mv;
225 mbmi->need_to_clamp_mvs = x->need_to_clamp_best_mvs; 291 mbmi->need_to_clamp_mvs = x->need_to_clamp_best_mvs;
226 mv_col = x->best_sse_mv.as_mv.col; 292 mv_col = x->best_sse_mv.as_mv.col;
227 mv_row = x->best_sse_mv.as_mv.row; 293 mv_row = x->best_sse_mv.as_mv.row;
294 // Bias to zero_mv if small amount of motion.
295 // Note sse_diff_thresh is intialized to zero, so this ensures
296 // we will always choose zero_mv for denoising if
297 // zero_mv_see <= best_sse (i.e., sse_diff <= 0).
298 if ((unsigned int)(mv_row * mv_row + mv_col * mv_col)
299 <= NOISE_MOTION_THRESHOLD)
300 sse_diff_thresh = (int)SSE_DIFF_THRESHOLD;
228 301
229 if (frame == INTRA_FRAME || 302 if (frame == INTRA_FRAME ||
230 ((unsigned int)(mv_row *mv_row + mv_col *mv_col) 303 sse_diff <= sse_diff_thresh)
231 <= NOISE_MOTION_THRESHOLD &&
232 sse_diff < (int)SSE_DIFF_THRESHOLD))
233 { 304 {
234 /* 305 /*
235 * Handle intra blocks as referring to last frame with zero motion 306 * Handle intra blocks as referring to last frame with zero motion
236 * and let the absolute pixel difference affect the filter factor. 307 * and let the absolute pixel difference affect the filter factor.
237 * Also consider small amount of motion as being random walk due 308 * Also consider small amount of motion as being random walk due
238 * to noise, if it doesn't mean that we get a much bigger error. 309 * to noise, if it doesn't mean that we get a much bigger error.
239 * Note that any changes to the mode info only affects the 310 * Note that any changes to the mode info only affects the
240 * denoising. 311 * denoising.
241 */ 312 */
242 mbmi->ref_frame = 313 mbmi->ref_frame =
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 int mc_avg_y_stride = denoiser->yv12_mc_running_avg.y_stride; 372 int mc_avg_y_stride = denoiser->yv12_mc_running_avg.y_stride;
302 unsigned char *running_avg_y = 373 unsigned char *running_avg_y =
303 denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset; 374 denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset;
304 int avg_y_stride = denoiser->yv12_running_avg[INTRA_FRAME].y_stride; 375 int avg_y_stride = denoiser->yv12_running_avg[INTRA_FRAME].y_stride;
305 376
306 /* Filter. */ 377 /* Filter. */
307 decision = vp8_denoiser_filter(mc_running_avg_y, mc_avg_y_stride, 378 decision = vp8_denoiser_filter(mc_running_avg_y, mc_avg_y_stride,
308 running_avg_y, avg_y_stride, 379 running_avg_y, avg_y_stride,
309 x->thismb, 16, motion_magnitude2, 380 x->thismb, 16, motion_magnitude2,
310 x->increase_denoising); 381 x->increase_denoising);
382 denoiser->denoise_state[block_index] = motion_magnitude2 > 0 ?
383 kFilterNonZeroMV : kFilterZeroMV;
311 } 384 }
312 if (decision == COPY_BLOCK) 385 if (decision == COPY_BLOCK)
313 { 386 {
314 /* No filtering of this block; it differs too much from the predictor, 387 /* No filtering of this block; it differs too much from the predictor,
315 * or the motion vector magnitude is considered too big. 388 * or the motion vector magnitude is considered too big.
316 */ 389 */
317 vp8_copy_mem16x16( 390 vp8_copy_mem16x16(
318 x->thismb, 16, 391 x->thismb, 16,
319 denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset , 392 denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset ,
320 denoiser->yv12_running_avg[INTRA_FRAME].y_stride); 393 denoiser->yv12_running_avg[INTRA_FRAME].y_stride);
394 denoiser->denoise_state[block_index] = kNoFilter;
395 }
396 // Option to selectively deblock the denoised signal.
397 if (apply_spatial_loop_filter) {
398 loop_filter_info lfi;
399 int apply_filter_col = 0;
400 int apply_filter_row = 0;
401 int apply_filter = 0;
402 int y_stride = denoiser->yv12_running_avg[INTRA_FRAME].y_stride;
403 int uv_stride =denoiser->yv12_running_avg[INTRA_FRAME].uv_stride;
404
405 // Fix filter level to some nominal value for now.
406 int filter_level = 32;
407
408 int hev_index = lfi_n->hev_thr_lut[INTER_FRAME][filter_level];
409 lfi.mblim = lfi_n->mblim[filter_level];
410 lfi.blim = lfi_n->blim[filter_level];
411 lfi.lim = lfi_n->lim[filter_level];
412 lfi.hev_thr = lfi_n->hev_thr[hev_index];
413
414 // Apply filter if there is a difference in the denoiser filter state
415 // between the current and left/top block, or if non-zero motion vector
416 // is used for the motion-compensated filtering.
417 if (mb_col > 0) {
418 apply_filter_col = !((denoiser->denoise_state[block_index] ==
419 denoiser->denoise_state[block_index - 1]) &&
420 denoiser->denoise_state[block_index] != kFilterNonZeroMV);
421 if (apply_filter_col) {
422 // Filter left vertical edge.
423 apply_filter = 1;
424 vp8_loop_filter_mbv(
425 denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset,
426 NULL, NULL, y_stride, uv_stride, &lfi);
427 }
428 }
429 if (mb_row > 0) {
430 apply_filter_row = !((denoiser->denoise_state[block_index] ==
431 denoiser->denoise_state[block_index - denoiser->num_mb_cols]) &&
432 denoiser->denoise_state[block_index] != kFilterNonZeroMV);
433 if (apply_filter_row) {
434 // Filter top horizontal edge.
435 apply_filter = 1;
436 vp8_loop_filter_mbh(
437 denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset,
438 NULL, NULL, y_stride, uv_stride, &lfi);
439 }
440 }
441 if (apply_filter) {
442 // Update the signal block |x|. Pixel changes are only to top and/or
443 // left boundary pixels: can we avoid full block copy here.
444 vp8_copy_mem16x16(
445 denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset,
446 y_stride, x->thismb, 16);
447 }
321 } 448 }
322 } 449 }
OLDNEW
« no previous file with comments | « source/libvpx/vp8/encoder/denoising.h ('k') | source/libvpx/vp8/encoder/encodeframe.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698