OLD | NEW |
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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 return 4; | 42 return 4; |
43 } | 43 } |
44 | 44 |
45 static int noise_motion_thresh(BLOCK_SIZE bs, int increase_denoising) { | 45 static int noise_motion_thresh(BLOCK_SIZE bs, int increase_denoising) { |
46 (void)bs; | 46 (void)bs; |
47 (void)increase_denoising; | 47 (void)increase_denoising; |
48 return 25 * 25; | 48 return 25 * 25; |
49 } | 49 } |
50 | 50 |
51 static unsigned int sse_thresh(BLOCK_SIZE bs, int increase_denoising) { | 51 static unsigned int sse_thresh(BLOCK_SIZE bs, int increase_denoising) { |
52 return (4 << b_width_log2_lookup[bs]) * | 52 return (1 << num_pels_log2_lookup[bs]) * (increase_denoising ? 60 : 40); |
53 (4 << b_height_log2_lookup[bs]) * | |
54 (increase_denoising ? 60 : 40); | |
55 } | 53 } |
56 | 54 |
57 static int sse_diff_thresh(BLOCK_SIZE bs, int increase_denoising, | 55 static int sse_diff_thresh(BLOCK_SIZE bs, int increase_denoising, |
58 int mv_row, int mv_col) { | 56 int mv_row, int mv_col) { |
59 if (mv_row * mv_row + mv_col * mv_col > | 57 if (mv_row * mv_row + mv_col * mv_col > |
60 noise_motion_thresh(bs, increase_denoising)) { | 58 noise_motion_thresh(bs, increase_denoising)) { |
61 return 0; | 59 return 0; |
62 } else { | 60 } else { |
63 return (4 << b_width_log2_lookup[bs]) * | 61 return (1 << num_pels_log2_lookup[bs]) * 20; |
64 (4 << b_height_log2_lookup[bs]) * 20; | |
65 } | 62 } |
66 } | 63 } |
67 | 64 |
68 int total_adj_strong_thresh(BLOCK_SIZE bs, int increase_denoising) { | 65 int total_adj_strong_thresh(BLOCK_SIZE bs, int increase_denoising) { |
69 return (4 << b_width_log2_lookup[bs]) * | 66 return (1 << num_pels_log2_lookup[bs]) * (increase_denoising ? 3 : 2); |
70 (4 << b_height_log2_lookup[bs]) * (increase_denoising ? 3 : 2); | |
71 } | 67 } |
72 | 68 |
73 static int total_adj_weak_thresh(BLOCK_SIZE bs, int increase_denoising) { | 69 static int total_adj_weak_thresh(BLOCK_SIZE bs, int increase_denoising) { |
74 return (4 << b_width_log2_lookup[bs]) * | 70 return (1 << num_pels_log2_lookup[bs]) * (increase_denoising ? 3 : 2); |
75 (4 << b_height_log2_lookup[bs]) * (increase_denoising ? 3 : 2); | |
76 } | 71 } |
77 | 72 |
78 // TODO(jackychen): If increase_denoising is enabled in the future, | 73 // TODO(jackychen): If increase_denoising is enabled in the future, |
79 // we might need to update the code for calculating 'total_adj' in | 74 // we might need to update the code for calculating 'total_adj' in |
80 // case the C code is not bit-exact with corresponding sse2 code. | 75 // case the C code is not bit-exact with corresponding sse2 code. |
81 int vp9_denoiser_filter_c(const uint8_t *sig, int sig_stride, | 76 int vp9_denoiser_filter_c(const uint8_t *sig, int sig_stride, |
82 const uint8_t *mc_avg, | 77 const uint8_t *mc_avg, |
83 int mc_avg_stride, | 78 int mc_avg_stride, |
84 uint8_t *avg, int avg_stride, | 79 uint8_t *avg, int avg_stride, |
85 int increase_denoising, | 80 int increase_denoising, |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 return FILTER_BLOCK; | 183 return FILTER_BLOCK; |
189 } | 184 } |
190 return COPY_BLOCK; | 185 return COPY_BLOCK; |
191 } | 186 } |
192 | 187 |
193 static uint8_t *block_start(uint8_t *framebuf, int stride, | 188 static uint8_t *block_start(uint8_t *framebuf, int stride, |
194 int mi_row, int mi_col) { | 189 int mi_row, int mi_col) { |
195 return framebuf + (stride * mi_row * 8) + (mi_col * 8); | 190 return framebuf + (stride * mi_row * 8) + (mi_col * 8); |
196 } | 191 } |
197 | 192 |
198 static void copy_block(uint8_t *dest, int dest_stride, | |
199 const uint8_t *src, int src_stride, BLOCK_SIZE bs) { | |
200 int r; | |
201 for (r = 0; r < (4 << b_height_log2_lookup[bs]); ++r) { | |
202 vpx_memcpy(dest, src, (4 << b_width_log2_lookup[bs])); | |
203 dest += dest_stride; | |
204 src += src_stride; | |
205 } | |
206 } | |
207 | |
208 static VP9_DENOISER_DECISION perform_motion_compensation(VP9_DENOISER *denoiser, | 193 static VP9_DENOISER_DECISION perform_motion_compensation(VP9_DENOISER *denoiser, |
209 MACROBLOCK *mb, | 194 MACROBLOCK *mb, |
210 BLOCK_SIZE bs, | 195 BLOCK_SIZE bs, |
211 int increase_denoising, | 196 int increase_denoising, |
212 int mi_row, | 197 int mi_row, |
213 int mi_col, | 198 int mi_col, |
214 PICK_MODE_CONTEXT *ctx, | 199 PICK_MODE_CONTEXT *ctx, |
215 int *motion_magnitude | 200 int *motion_magnitude |
216 ) { | 201 ) { |
217 int mv_col, mv_row; | 202 int mv_col, mv_row; |
218 int sse_diff = ctx->zeromv_sse - ctx->newmv_sse; | 203 int sse_diff = ctx->zeromv_sse - ctx->newmv_sse; |
219 MV_REFERENCE_FRAME frame; | 204 MV_REFERENCE_FRAME frame; |
220 MACROBLOCKD *filter_mbd = &mb->e_mbd; | 205 MACROBLOCKD *filter_mbd = &mb->e_mbd; |
221 MB_MODE_INFO *mbmi = &filter_mbd->mi[0].src_mi->mbmi; | 206 MB_MODE_INFO *mbmi = &filter_mbd->mi[0].src_mi->mbmi; |
222 | |
223 MB_MODE_INFO saved_mbmi; | 207 MB_MODE_INFO saved_mbmi; |
224 int i, j; | 208 int i, j; |
225 struct buf_2d saved_dst[MAX_MB_PLANE]; | 209 struct buf_2d saved_dst[MAX_MB_PLANE]; |
226 struct buf_2d saved_pre[MAX_MB_PLANE][2]; // 2 pre buffers | 210 struct buf_2d saved_pre[MAX_MB_PLANE][2]; // 2 pre buffers |
227 | 211 |
228 // We will restore these after motion compensation. | |
229 saved_mbmi = *mbmi; | |
230 for (i = 0; i < MAX_MB_PLANE; ++i) { | |
231 for (j = 0; j < 2; ++j) { | |
232 saved_pre[i][j] = filter_mbd->plane[i].pre[j]; | |
233 } | |
234 saved_dst[i] = filter_mbd->plane[i].dst; | |
235 } | |
236 | |
237 mv_col = ctx->best_sse_mv.as_mv.col; | 212 mv_col = ctx->best_sse_mv.as_mv.col; |
238 mv_row = ctx->best_sse_mv.as_mv.row; | 213 mv_row = ctx->best_sse_mv.as_mv.row; |
| 214 *motion_magnitude = mv_row * mv_row + mv_col * mv_col; |
| 215 frame = ctx->best_reference_frame; |
239 | 216 |
240 *motion_magnitude = mv_row * mv_row + mv_col * mv_col; | 217 saved_mbmi = *mbmi; |
241 | |
242 frame = ctx->best_reference_frame; | |
243 | 218 |
244 // If the best reference frame uses inter-prediction and there is enough of a | 219 // If the best reference frame uses inter-prediction and there is enough of a |
245 // difference in sum-squared-error, use it. | 220 // difference in sum-squared-error, use it. |
246 if (frame != INTRA_FRAME && | 221 if (frame != INTRA_FRAME && |
247 sse_diff > sse_diff_thresh(bs, increase_denoising, mv_row, mv_col)) { | 222 sse_diff > sse_diff_thresh(bs, increase_denoising, mv_row, mv_col)) { |
248 mbmi->ref_frame[0] = ctx->best_reference_frame; | 223 mbmi->ref_frame[0] = ctx->best_reference_frame; |
249 mbmi->mode = ctx->best_sse_inter_mode; | 224 mbmi->mode = ctx->best_sse_inter_mode; |
250 mbmi->mv[0] = ctx->best_sse_mv; | 225 mbmi->mv[0] = ctx->best_sse_mv; |
251 } else { | 226 } else { |
252 // Otherwise, use the zero reference frame. | 227 // Otherwise, use the zero reference frame. |
253 frame = ctx->best_zeromv_reference_frame; | 228 frame = ctx->best_zeromv_reference_frame; |
254 | 229 |
255 mbmi->ref_frame[0] = ctx->best_zeromv_reference_frame; | 230 mbmi->ref_frame[0] = ctx->best_zeromv_reference_frame; |
256 mbmi->mode = ZEROMV; | 231 mbmi->mode = ZEROMV; |
257 mbmi->mv[0].as_int = 0; | 232 mbmi->mv[0].as_int = 0; |
258 | 233 |
259 ctx->best_sse_inter_mode = ZEROMV; | 234 ctx->best_sse_inter_mode = ZEROMV; |
260 ctx->best_sse_mv.as_int = 0; | 235 ctx->best_sse_mv.as_int = 0; |
261 ctx->newmv_sse = ctx->zeromv_sse; | 236 ctx->newmv_sse = ctx->zeromv_sse; |
262 } | 237 } |
263 | 238 |
| 239 if (ctx->newmv_sse > sse_thresh(bs, increase_denoising)) { |
| 240 // Restore everything to its original state |
| 241 *mbmi = saved_mbmi; |
| 242 return COPY_BLOCK; |
| 243 } |
| 244 if (mv_row * mv_row + mv_col * mv_col > |
| 245 8 * noise_motion_thresh(bs, increase_denoising)) { |
| 246 // Restore everything to its original state |
| 247 *mbmi = saved_mbmi; |
| 248 return COPY_BLOCK; |
| 249 } |
| 250 |
| 251 // We will restore these after motion compensation. |
| 252 for (i = 0; i < MAX_MB_PLANE; ++i) { |
| 253 for (j = 0; j < 2; ++j) { |
| 254 saved_pre[i][j] = filter_mbd->plane[i].pre[j]; |
| 255 } |
| 256 saved_dst[i] = filter_mbd->plane[i].dst; |
| 257 } |
| 258 |
264 // Set the pointers in the MACROBLOCKD to point to the buffers in the denoiser | 259 // Set the pointers in the MACROBLOCKD to point to the buffers in the denoiser |
265 // struct. | 260 // struct. |
266 for (j = 0; j < 2; ++j) { | 261 for (j = 0; j < 2; ++j) { |
267 filter_mbd->plane[0].pre[j].buf = | 262 filter_mbd->plane[0].pre[j].buf = |
268 block_start(denoiser->running_avg_y[frame].y_buffer, | 263 block_start(denoiser->running_avg_y[frame].y_buffer, |
269 denoiser->running_avg_y[frame].y_stride, | 264 denoiser->running_avg_y[frame].y_stride, |
270 mi_row, mi_col); | 265 mi_row, mi_col); |
271 filter_mbd->plane[0].pre[j].stride = | 266 filter_mbd->plane[0].pre[j].stride = |
272 denoiser->running_avg_y[frame].y_stride; | 267 denoiser->running_avg_y[frame].y_stride; |
273 filter_mbd->plane[1].pre[j].buf = | 268 filter_mbd->plane[1].pre[j].buf = |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 for (i = 0; i < MAX_MB_PLANE; ++i) { | 301 for (i = 0; i < MAX_MB_PLANE; ++i) { |
307 for (j = 0; j < 2; ++j) { | 302 for (j = 0; j < 2; ++j) { |
308 filter_mbd->plane[i].pre[j] = saved_pre[i][j]; | 303 filter_mbd->plane[i].pre[j] = saved_pre[i][j]; |
309 } | 304 } |
310 filter_mbd->plane[i].dst = saved_dst[i]; | 305 filter_mbd->plane[i].dst = saved_dst[i]; |
311 } | 306 } |
312 | 307 |
313 mv_row = ctx->best_sse_mv.as_mv.row; | 308 mv_row = ctx->best_sse_mv.as_mv.row; |
314 mv_col = ctx->best_sse_mv.as_mv.col; | 309 mv_col = ctx->best_sse_mv.as_mv.col; |
315 | 310 |
316 if (ctx->newmv_sse > sse_thresh(bs, increase_denoising)) { | |
317 return COPY_BLOCK; | |
318 } | |
319 if (mv_row * mv_row + mv_col * mv_col > | |
320 8 * noise_motion_thresh(bs, increase_denoising)) { | |
321 return COPY_BLOCK; | |
322 } | |
323 return FILTER_BLOCK; | 311 return FILTER_BLOCK; |
324 } | 312 } |
325 | 313 |
326 void vp9_denoiser_denoise(VP9_DENOISER *denoiser, MACROBLOCK *mb, | 314 void vp9_denoiser_denoise(VP9_DENOISER *denoiser, MACROBLOCK *mb, |
327 int mi_row, int mi_col, BLOCK_SIZE bs, | 315 int mi_row, int mi_col, BLOCK_SIZE bs, |
328 PICK_MODE_CONTEXT *ctx) { | 316 PICK_MODE_CONTEXT *ctx) { |
329 int motion_magnitude = 0; | 317 int motion_magnitude = 0; |
330 VP9_DENOISER_DECISION decision = FILTER_BLOCK; | 318 VP9_DENOISER_DECISION decision = FILTER_BLOCK; |
331 YV12_BUFFER_CONFIG avg = denoiser->running_avg_y[INTRA_FRAME]; | 319 YV12_BUFFER_CONFIG avg = denoiser->running_avg_y[INTRA_FRAME]; |
332 YV12_BUFFER_CONFIG mc_avg = denoiser->mc_running_avg_y; | 320 YV12_BUFFER_CONFIG mc_avg = denoiser->mc_running_avg_y; |
333 uint8_t *avg_start = block_start(avg.y_buffer, avg.y_stride, mi_row, mi_col); | 321 uint8_t *avg_start = block_start(avg.y_buffer, avg.y_stride, mi_row, mi_col); |
334 uint8_t *mc_avg_start = block_start(mc_avg.y_buffer, mc_avg.y_stride, | 322 uint8_t *mc_avg_start = block_start(mc_avg.y_buffer, mc_avg.y_stride, |
335 mi_row, mi_col); | 323 mi_row, mi_col); |
336 struct buf_2d src = mb->plane[0].src; | 324 struct buf_2d src = mb->plane[0].src; |
337 | 325 |
338 decision = perform_motion_compensation(denoiser, mb, bs, | 326 decision = perform_motion_compensation(denoiser, mb, bs, |
339 denoiser->increase_denoising, | 327 denoiser->increase_denoising, |
340 mi_row, mi_col, ctx, | 328 mi_row, mi_col, ctx, |
341 &motion_magnitude); | 329 &motion_magnitude); |
342 | 330 |
343 if (decision == FILTER_BLOCK) { | 331 if (decision == FILTER_BLOCK) { |
344 decision = vp9_denoiser_filter(src.buf, src.stride, | 332 decision = vp9_denoiser_filter(src.buf, src.stride, |
345 mc_avg_start, mc_avg.y_stride, | 333 mc_avg_start, mc_avg.y_stride, |
346 avg_start, avg.y_stride, | 334 avg_start, avg.y_stride, |
347 0, bs, motion_magnitude); | 335 0, bs, motion_magnitude); |
348 } | 336 } |
349 | 337 |
350 if (decision == FILTER_BLOCK) { | 338 if (decision == FILTER_BLOCK) { |
351 copy_block(src.buf, src.stride, avg_start, avg.y_stride, bs); | 339 vp9_convolve_copy(avg_start, avg.y_stride, src.buf, src.stride, |
| 340 NULL, 0, NULL, 0, |
| 341 num_4x4_blocks_wide_lookup[bs] << 2, |
| 342 num_4x4_blocks_high_lookup[bs] << 2); |
352 } else { // COPY_BLOCK | 343 } else { // COPY_BLOCK |
353 copy_block(avg_start, avg.y_stride, src.buf, src.stride, bs); | 344 vp9_convolve_copy(src.buf, src.stride, avg_start, avg.y_stride, |
| 345 NULL, 0, NULL, 0, |
| 346 num_4x4_blocks_wide_lookup[bs] << 2, |
| 347 num_4x4_blocks_high_lookup[bs] << 2); |
354 } | 348 } |
355 } | 349 } |
356 | 350 |
357 static void copy_frame(YV12_BUFFER_CONFIG dest, const YV12_BUFFER_CONFIG src) { | 351 static void copy_frame(YV12_BUFFER_CONFIG dest, const YV12_BUFFER_CONFIG src) { |
358 int r; | 352 int r; |
359 const uint8_t *srcbuf = src.y_buffer; | 353 const uint8_t *srcbuf = src.y_buffer; |
360 uint8_t *destbuf = dest.y_buffer; | 354 uint8_t *destbuf = dest.y_buffer; |
361 assert(dest.y_width == src.y_width); | 355 assert(dest.y_width == src.y_width); |
362 assert(dest.y_height == src.y_height); | 356 assert(dest.y_height == src.y_height); |
363 | 357 |
364 for (r = 0; r < dest.y_height; ++r) { | 358 for (r = 0; r < dest.y_height; ++r) { |
365 vpx_memcpy(destbuf, srcbuf, dest.y_width); | 359 vpx_memcpy(destbuf, srcbuf, dest.y_width); |
366 destbuf += dest.y_stride; | 360 destbuf += dest.y_stride; |
367 srcbuf += src.y_stride; | 361 srcbuf += src.y_stride; |
368 } | 362 } |
369 } | 363 } |
370 | 364 |
| 365 static void swap_frame_buffer(YV12_BUFFER_CONFIG dest, |
| 366 YV12_BUFFER_CONFIG src) { |
| 367 uint8_t *tmp_buf = dest.y_buffer; |
| 368 assert(dest.y_width == src.y_width); |
| 369 assert(dest.y_height == src.y_height); |
| 370 dest.y_buffer = src.y_buffer; |
| 371 src.y_buffer = tmp_buf; |
| 372 } |
| 373 |
371 void vp9_denoiser_update_frame_info(VP9_DENOISER *denoiser, | 374 void vp9_denoiser_update_frame_info(VP9_DENOISER *denoiser, |
372 YV12_BUFFER_CONFIG src, | 375 YV12_BUFFER_CONFIG src, |
373 FRAME_TYPE frame_type, | 376 FRAME_TYPE frame_type, |
374 int refresh_alt_ref_frame, | 377 int refresh_alt_ref_frame, |
375 int refresh_golden_frame, | 378 int refresh_golden_frame, |
376 int refresh_last_frame) { | 379 int refresh_last_frame) { |
377 if (frame_type == KEY_FRAME) { | 380 if (frame_type == KEY_FRAME) { |
378 int i; | 381 int i; |
379 // Start at 1 so as not to overwrite the INTRA_FRAME | 382 // Start at 1 so as not to overwrite the INTRA_FRAME |
380 for (i = 1; i < MAX_REF_FRAMES; ++i) { | 383 for (i = 1; i < MAX_REF_FRAMES; ++i) |
381 copy_frame(denoiser->running_avg_y[i], src); | 384 copy_frame(denoiser->running_avg_y[i], src); |
382 } | 385 return; |
383 } else { /* For non key frames */ | 386 } |
384 if (refresh_alt_ref_frame) { | 387 |
385 copy_frame(denoiser->running_avg_y[ALTREF_FRAME], | 388 /* For non key frames */ |
386 denoiser->running_avg_y[INTRA_FRAME]); | 389 if (refresh_alt_ref_frame) { |
387 } | 390 swap_frame_buffer(denoiser->running_avg_y[ALTREF_FRAME], |
388 if (refresh_golden_frame) { | 391 denoiser->running_avg_y[INTRA_FRAME]); |
389 copy_frame(denoiser->running_avg_y[GOLDEN_FRAME], | 392 } |
390 denoiser->running_avg_y[INTRA_FRAME]); | 393 if (refresh_golden_frame) { |
391 } | 394 swap_frame_buffer(denoiser->running_avg_y[GOLDEN_FRAME], |
392 if (refresh_last_frame) { | 395 denoiser->running_avg_y[INTRA_FRAME]); |
393 copy_frame(denoiser->running_avg_y[LAST_FRAME], | 396 } |
394 denoiser->running_avg_y[INTRA_FRAME]); | 397 if (refresh_last_frame) { |
395 } | 398 swap_frame_buffer(denoiser->running_avg_y[LAST_FRAME], |
| 399 denoiser->running_avg_y[INTRA_FRAME]); |
396 } | 400 } |
397 } | 401 } |
398 | 402 |
399 void vp9_denoiser_reset_frame_stats(PICK_MODE_CONTEXT *ctx) { | 403 void vp9_denoiser_reset_frame_stats(PICK_MODE_CONTEXT *ctx) { |
400 ctx->zeromv_sse = UINT_MAX; | 404 ctx->zeromv_sse = UINT_MAX; |
401 ctx->newmv_sse = UINT_MAX; | 405 // This should be initialized as zero since mode search stage might skip |
| 406 // NEWMV mode if inferred motion vector modes provide sufficiently good |
| 407 // prediction quality. |
| 408 ctx->newmv_sse = 0; |
402 } | 409 } |
403 | 410 |
404 void vp9_denoiser_update_frame_stats(MB_MODE_INFO *mbmi, unsigned int sse, | 411 void vp9_denoiser_update_frame_stats(MB_MODE_INFO *mbmi, unsigned int sse, |
405 PREDICTION_MODE mode, | 412 PREDICTION_MODE mode, |
406 PICK_MODE_CONTEXT *ctx) { | 413 PICK_MODE_CONTEXT *ctx) { |
407 // TODO(tkopp): Use both MVs if possible | 414 // TODO(tkopp): Use both MVs if possible |
408 if (mbmi->mv[0].as_int == 0 && sse < ctx->zeromv_sse) { | 415 if (mbmi->mv[0].as_int == 0 && sse < ctx->zeromv_sse) { |
409 ctx->zeromv_sse = sse; | 416 ctx->zeromv_sse = sse; |
410 ctx->best_zeromv_reference_frame = mbmi->ref_frame[0]; | 417 ctx->best_zeromv_reference_frame = mbmi->ref_frame[0]; |
411 } | 418 } |
412 | 419 |
413 if (mode == NEWMV) { | 420 if (mode == NEWMV) { |
414 ctx->newmv_sse = sse; | 421 ctx->newmv_sse = sse; |
415 ctx->best_sse_inter_mode = mode; | 422 ctx->best_sse_inter_mode = mode; |
416 ctx->best_sse_mv = mbmi->mv[0]; | 423 ctx->best_sse_mv = mbmi->mv[0]; |
417 ctx->best_reference_frame = mbmi->ref_frame[0]; | 424 ctx->best_reference_frame = mbmi->ref_frame[0]; |
418 } | 425 } |
419 } | 426 } |
420 | 427 |
421 int vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height, | 428 int vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height, |
422 int ssx, int ssy, | 429 int ssx, int ssy, |
423 #if CONFIG_VP9_HIGHBITDEPTH | 430 #if CONFIG_VP9_HIGHBITDEPTH |
424 int use_highbitdepth, | 431 int use_highbitdepth, |
425 #endif | 432 #endif |
426 int border) { | 433 int border) { |
427 int i, fail; | 434 int i, fail; |
| 435 const int legacy_byte_alignment = 0; |
428 assert(denoiser != NULL); | 436 assert(denoiser != NULL); |
429 | 437 |
430 for (i = 0; i < MAX_REF_FRAMES; ++i) { | 438 for (i = 0; i < MAX_REF_FRAMES; ++i) { |
431 fail = vp9_alloc_frame_buffer(&denoiser->running_avg_y[i], width, height, | 439 fail = vp9_alloc_frame_buffer(&denoiser->running_avg_y[i], width, height, |
432 ssx, ssy, | 440 ssx, ssy, |
433 #if CONFIG_VP9_HIGHBITDEPTH | 441 #if CONFIG_VP9_HIGHBITDEPTH |
434 use_highbitdepth, | 442 use_highbitdepth, |
435 #endif | 443 #endif |
436 border); | 444 border, legacy_byte_alignment); |
437 if (fail) { | 445 if (fail) { |
438 vp9_denoiser_free(denoiser); | 446 vp9_denoiser_free(denoiser); |
439 return 1; | 447 return 1; |
440 } | 448 } |
441 #ifdef OUTPUT_YUV_DENOISED | 449 #ifdef OUTPUT_YUV_DENOISED |
442 make_grayscale(&denoiser->running_avg_y[i]); | 450 make_grayscale(&denoiser->running_avg_y[i]); |
443 #endif | 451 #endif |
444 } | 452 } |
445 | 453 |
446 fail = vp9_alloc_frame_buffer(&denoiser->mc_running_avg_y, width, height, | 454 fail = vp9_alloc_frame_buffer(&denoiser->mc_running_avg_y, width, height, |
447 ssx, ssy, | 455 ssx, ssy, |
448 #if CONFIG_VP9_HIGHBITDEPTH | 456 #if CONFIG_VP9_HIGHBITDEPTH |
449 use_highbitdepth, | 457 use_highbitdepth, |
450 #endif | 458 #endif |
451 border); | 459 border, legacy_byte_alignment); |
452 if (fail) { | 460 if (fail) { |
453 vp9_denoiser_free(denoiser); | 461 vp9_denoiser_free(denoiser); |
454 return 1; | 462 return 1; |
455 } | 463 } |
456 #ifdef OUTPUT_YUV_DENOISED | 464 #ifdef OUTPUT_YUV_DENOISED |
457 make_grayscale(&denoiser->running_avg_y[i]); | 465 make_grayscale(&denoiser->running_avg_y[i]); |
458 #endif | 466 #endif |
459 denoiser->increase_denoising = 0; | 467 denoiser->increase_denoising = 0; |
| 468 denoiser->frame_buffer_initialized = 1; |
460 | 469 |
461 return 0; | 470 return 0; |
462 } | 471 } |
463 | 472 |
464 void vp9_denoiser_free(VP9_DENOISER *denoiser) { | 473 void vp9_denoiser_free(VP9_DENOISER *denoiser) { |
465 int i; | 474 int i; |
| 475 denoiser->frame_buffer_initialized = 0; |
466 if (denoiser == NULL) { | 476 if (denoiser == NULL) { |
467 return; | 477 return; |
468 } | 478 } |
469 for (i = 0; i < MAX_REF_FRAMES; ++i) { | 479 for (i = 0; i < MAX_REF_FRAMES; ++i) { |
470 if (&denoiser->running_avg_y[i] != NULL) { | 480 if (&denoiser->running_avg_y[i] != NULL) { |
471 vp9_free_frame_buffer(&denoiser->running_avg_y[i]); | 481 vp9_free_frame_buffer(&denoiser->running_avg_y[i]); |
472 } | 482 } |
473 } | 483 } |
474 if (&denoiser->mc_running_avg_y != NULL) { | 484 if (&denoiser->mc_running_avg_y != NULL) { |
475 vp9_free_frame_buffer(&denoiser->mc_running_avg_y); | 485 vp9_free_frame_buffer(&denoiser->mc_running_avg_y); |
476 } | 486 } |
477 } | 487 } |
478 | 488 |
479 #ifdef OUTPUT_YUV_DENOISED | 489 #ifdef OUTPUT_YUV_DENOISED |
480 static void make_grayscale(YV12_BUFFER_CONFIG *yuv) { | 490 static void make_grayscale(YV12_BUFFER_CONFIG *yuv) { |
481 int r, c; | 491 int r, c; |
482 uint8_t *u = yuv->u_buffer; | 492 uint8_t *u = yuv->u_buffer; |
483 uint8_t *v = yuv->v_buffer; | 493 uint8_t *v = yuv->v_buffer; |
484 | 494 |
485 // The '/2's are there because we have a 440 buffer, but we want to output | 495 for (r = 0; r < yuv->uv_height; ++r) { |
486 // 420. | 496 for (c = 0; c < yuv->uv_width; ++c) { |
487 for (r = 0; r < yuv->uv_height / 2; ++r) { | |
488 for (c = 0; c < yuv->uv_width / 2; ++c) { | |
489 u[c] = UINT8_MAX / 2; | 497 u[c] = UINT8_MAX / 2; |
490 v[c] = UINT8_MAX / 2; | 498 v[c] = UINT8_MAX / 2; |
491 } | 499 } |
492 u += yuv->uv_stride + yuv->uv_width / 2; | 500 u += yuv->uv_stride; |
493 v += yuv->uv_stride + yuv->uv_width / 2; | 501 v += yuv->uv_stride; |
494 } | 502 } |
495 } | 503 } |
496 #endif | 504 #endif |
OLD | NEW |