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

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

Issue 375983002: libvpx: Pull from upstream (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/libvpx/
Patch Set: Created 6 years, 5 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.h » ('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
11 #include <assert.h> 11 #include <assert.h>
12 #include <limits.h>
12 #include "vpx_scale/yv12config.h" 13 #include "vpx_scale/yv12config.h"
13 #include "vpx/vpx_integer.h" 14 #include "vpx/vpx_integer.h"
15 #include "vp9/common/vp9_reconinter.h"
14 #include "vp9/encoder/vp9_denoiser.h" 16 #include "vp9/encoder/vp9_denoiser.h"
15 17
18 /* The VP9 denoiser is a work-in-progress. It currently is only designed to work
19 * with speed 6, though it (inexplicably) seems to also work with speed 5 (one
20 * would need to modify the source code in vp9_pickmode.c and vp9_encoder.c to
21 * make the calls to the vp9_denoiser_* functions when in speed 5).
22 *
23 * The implementation is very similar to that of the VP8 denoiser. While
24 * choosing the motion vectors / reference frames, the denoiser is run, and if
25 * it did not modify the signal to much, the denoised block is copied to the
26 * signal.
27 */
28
29 #ifdef OUTPUT_YUV_DENOISED
30 static void make_grayscale(YV12_BUFFER_CONFIG *yuv);
31 #endif
32
16 static const int widths[] = {4, 4, 8, 8, 8, 16, 16, 16, 32, 32, 32, 64, 64}; 33 static const int widths[] = {4, 4, 8, 8, 8, 16, 16, 16, 32, 32, 32, 64, 64};
17 static const int heights[] = {4, 8, 4, 8, 16, 8, 16, 32, 16, 32, 64, 32, 64}; 34 static const int heights[] = {4, 8, 4, 8, 16, 8, 16, 32, 16, 32, 64, 32, 64};
18 35
19 int vp9_denoiser_filter() { 36 static int absdiff_thresh(BLOCK_SIZE bs, int increase_denoising) {
20 return 0; 37 (void)bs;
38 return 3 + (increase_denoising ? 1 : 0);
21 } 39 }
22 40
23 static int update_running_avg(const uint8_t *mc_avg, int mc_avg_stride, 41 static int delta_thresh(BLOCK_SIZE bs, int increase_denoising) {
24 uint8_t *avg, int avg_stride, 42 (void)bs;
25 const uint8_t *sig, int sig_stride, 43 (void)increase_denoising;
26 int increase_denoising, BLOCK_SIZE bs) { 44 return 4;
45 }
46
47 static int noise_motion_thresh(BLOCK_SIZE bs, int increase_denoising) {
48 (void)bs;
49 (void)increase_denoising;
50 return 25 * 25;
51 }
52
53 static unsigned int sse_thresh(BLOCK_SIZE bs, int increase_denoising) {
54 return widths[bs] * heights[bs] * (increase_denoising ? 60 : 40);
55 }
56
57 static int sse_diff_thresh(BLOCK_SIZE bs, int increase_denoising,
58 int mv_row, int mv_col) {
59 if (mv_row * mv_row + mv_col * mv_col >
60 noise_motion_thresh(bs, increase_denoising)) {
61 return 0;
62 } else {
63 return widths[bs] * heights[bs] * 20;
64 }
65 }
66
67 static int total_adj_strong_thresh(BLOCK_SIZE bs, int increase_denoising) {
68 return widths[bs] * heights[bs] * (increase_denoising ? 3 : 2);
69 }
70
71 static int total_adj_weak_thresh(BLOCK_SIZE bs, int increase_denoising) {
72 return widths[bs] * heights[bs] * (increase_denoising ? 3 : 2);
73 }
74
75 static VP9_DENOISER_DECISION denoiser_filter(const uint8_t *sig, int sig_stride,
76 const uint8_t *mc_avg,
77 int mc_avg_stride,
78 uint8_t *avg, int avg_stride,
79 int increase_denoising,
80 BLOCK_SIZE bs) {
27 int r, c; 81 int r, c;
28 int diff, adj, absdiff; 82 const uint8_t *sig_start = sig;
29 int shift_inc1 = 0, shift_inc2 = 1; 83 const uint8_t *mc_avg_start = mc_avg;
84 uint8_t *avg_start = avg;
85 int diff, adj, absdiff, delta;
30 int adj_val[] = {3, 4, 6}; 86 int adj_val[] = {3, 4, 6};
31 int total_adj = 0; 87 int total_adj = 0;
32 88
33 if (increase_denoising) { 89 // First attempt to apply a strong temporal denoising filter.
34 shift_inc1 = 1;
35 shift_inc2 = 2;
36 }
37
38 for (r = 0; r < heights[bs]; ++r) { 90 for (r = 0; r < heights[bs]; ++r) {
39 for (c = 0; c < widths[bs]; ++c) { 91 for (c = 0; c < widths[bs]; ++c) {
40 diff = mc_avg[c] - sig[c]; 92 diff = mc_avg[c] - sig[c];
41 absdiff = abs(diff); 93 absdiff = abs(diff);
42 94
43 if (absdiff <= 3 + shift_inc1) { 95 if (absdiff <= absdiff_thresh(bs, increase_denoising)) {
44 avg[c] = mc_avg[c]; 96 avg[c] = mc_avg[c];
45 total_adj += diff; 97 total_adj += diff;
46 } else { 98 } else {
47 switch (absdiff) { 99 switch (absdiff) {
48 case 4: case 5: case 6: case 7: 100 case 4: case 5: case 6: case 7:
49 adj = adj_val[0]; 101 adj = adj_val[0];
50 break; 102 break;
51 case 8: case 9: case 10: case 11: 103 case 8: case 9: case 10: case 11:
52 case 12: case 13: case 14: case 15: 104 case 12: case 13: case 14: case 15:
53 adj = adj_val[1]; 105 adj = adj_val[1];
54 break; 106 break;
55 default: 107 default:
56 adj = adj_val[2]; 108 adj = adj_val[2];
57 } 109 }
58 if (diff > 0) { 110 if (diff > 0) {
59 avg[c] = MIN(UINT8_MAX, sig[c] + adj); 111 avg[c] = MIN(UINT8_MAX, sig[c] + adj);
60 total_adj += adj; 112 total_adj += adj;
61 } else { 113 } else {
62 avg[c] = MAX(0, sig[c] - adj); 114 avg[c] = MAX(0, sig[c] - adj);
63 total_adj -= adj; 115 total_adj -= adj;
64 } 116 }
65 } 117 }
66 } 118 }
67 sig += sig_stride; 119 sig += sig_stride;
68 avg += avg_stride; 120 avg += avg_stride;
69 mc_avg += mc_avg_stride; 121 mc_avg += mc_avg_stride;
70 } 122 }
71 return total_adj; 123
124 // If the strong filter did not modify the signal too much, we're all set.
125 if (abs(total_adj) <= total_adj_strong_thresh(bs, increase_denoising)) {
126 return FILTER_BLOCK;
127 }
128
129 // Otherwise, we try to dampen the filter if the delta is not too high.
130 delta = ((abs(total_adj) - total_adj_strong_thresh(bs, increase_denoising))
131 >> 8) + 1;
132 if (delta > delta_thresh(bs, increase_denoising)) {
133 return COPY_BLOCK;
134 }
135
136 mc_avg = mc_avg_start;
137 avg = avg_start;
138 sig = sig_start;
139 for (r = 0; r < heights[bs]; ++r) {
140 for (c = 0; c < widths[bs]; ++c) {
141 diff = mc_avg[c] - sig[c];
142 adj = abs(diff);
143 if (adj > delta) {
144 adj = delta;
145 }
146 if (diff > 0) {
147 avg[c] = MAX(0, avg[c] - adj);
148 total_adj += adj;
149 } else {
150 avg[c] = MIN(UINT8_MAX, avg[c] + adj);
151 total_adj -= adj;
152 }
153 }
154 sig += sig_stride;
155 avg += avg_stride;
156 mc_avg += mc_avg_stride;
157 }
158
159 // We can use the filter if it has been sufficiently dampened
160 if (abs(total_adj) <= total_adj_weak_thresh(bs, increase_denoising)) {
161 return FILTER_BLOCK;
162 }
163 return COPY_BLOCK;
72 } 164 }
73 165
74 static uint8_t *block_start(uint8_t *framebuf, int stride, 166 static uint8_t *block_start(uint8_t *framebuf, int stride,
75 int mi_row, int mi_col) { 167 int mi_row, int mi_col) {
76 return framebuf + (stride * mi_row * 8) + (mi_col * 8); 168 return framebuf + (stride * mi_row * 8) + (mi_col * 8);
77 } 169 }
78 170
79 void copy_block(uint8_t *dest, int dest_stride, 171 static void copy_block(uint8_t *dest, int dest_stride,
80 uint8_t *src, int src_stride, BLOCK_SIZE bs) { 172 const uint8_t *src, int src_stride, BLOCK_SIZE bs) {
81 int r, c; 173 int r;
82 for (r = 0; r < heights[bs]; ++r) { 174 for (r = 0; r < heights[bs]; ++r) {
83 for (c = 0; c < widths[bs]; ++c) { 175 vpx_memcpy(dest, src, widths[bs]);
84 dest[c] = src[c];
85 }
86 dest += dest_stride; 176 dest += dest_stride;
87 src += src_stride; 177 src += src_stride;
88 } 178 }
89 } 179 }
90 180
181 static VP9_DENOISER_DECISION perform_motion_compensation(VP9_DENOISER *denoiser,
182 MACROBLOCK *mb,
183 BLOCK_SIZE bs,
184 int increase_denoising,
185 int mi_row,
186 int mi_col) {
187 int mv_col, mv_row;
188 int sse_diff = denoiser->zero_mv_sse - denoiser->best_sse;
189 MV_REFERENCE_FRAME frame;
190 MACROBLOCKD *filter_mbd = &mb->e_mbd;
191 MB_MODE_INFO *mbmi = &filter_mbd->mi[0]->mbmi;
192
193 // We will restore these after motion compensation.
194 MB_MODE_INFO saved_mbmi = *mbmi;
195 struct buf_2d saved_dst = filter_mbd->plane[0].dst;
196 struct buf_2d saved_pre[2];
197 saved_pre[0] = filter_mbd->plane[0].pre[0];
198 saved_pre[1] = filter_mbd->plane[0].pre[1];
199
200 mv_col = denoiser->best_sse_mv.as_mv.col;
201 mv_row = denoiser->best_sse_mv.as_mv.row;
202
203 frame = denoiser->best_reference_frame;
204
205 // If the best reference frame uses inter-prediction and there is enough of a
206 // difference in sum-squared-error, use it.
207 if (frame != INTRA_FRAME &&
208 sse_diff > sse_diff_thresh(bs, increase_denoising, mv_row, mv_col)) {
209 mbmi->ref_frame[0] = denoiser->best_reference_frame;
210 mbmi->mode = denoiser->best_sse_inter_mode;
211 mbmi->mv[0] = denoiser->best_sse_mv;
212 } else {
213 // Otherwise, use the zero reference frame.
214 frame = denoiser->best_zeromv_reference_frame;
215
216 mbmi->ref_frame[0] = denoiser->best_zeromv_reference_frame;
217 mbmi->mode = ZEROMV;
218 mbmi->mv[0].as_int = 0;
219
220 denoiser->best_sse_inter_mode = ZEROMV;
221 denoiser->best_sse_mv.as_int = 0;
222 denoiser->best_sse = denoiser->zero_mv_sse;
223 }
224
225 // Set the pointers in the MACROBLOCKD to point to the buffers in the denoiser
226 // struct.
227 filter_mbd->plane[0].pre[0].buf =
228 block_start(denoiser->running_avg_y[frame].y_buffer,
229 denoiser->running_avg_y[frame].y_stride,
230 mi_row, mi_col);
231 filter_mbd->plane[0].pre[0].stride = denoiser->running_avg_y[frame].y_stride;
232
233 filter_mbd->plane[1].pre[0].buf =
234 block_start(denoiser->running_avg_y[frame].u_buffer,
235 denoiser->running_avg_y[frame].uv_stride,
236 mi_row, mi_col);
237 filter_mbd->plane[1].pre[0].stride = denoiser->running_avg_y[frame].uv_stride;
238
239 filter_mbd->plane[2].pre[0].buf =
240 block_start(denoiser->running_avg_y[frame].v_buffer,
241 denoiser->running_avg_y[frame].uv_stride,
242 mi_row, mi_col);
243 filter_mbd->plane[2].pre[0].stride = denoiser->running_avg_y[frame].uv_stride;
244
245 filter_mbd->plane[0].pre[1].buf =
246 block_start(denoiser->running_avg_y[frame].y_buffer,
247 denoiser->running_avg_y[frame].y_stride,
248 mi_row, mi_col);
249 filter_mbd->plane[0].pre[1].stride = denoiser->running_avg_y[frame].y_stride;
250
251 filter_mbd->plane[1].pre[1].buf =
252 block_start(denoiser->running_avg_y[frame].u_buffer,
253 denoiser->running_avg_y[frame].uv_stride,
254 mi_row, mi_col);
255 filter_mbd->plane[1].pre[1].stride = denoiser->running_avg_y[frame].uv_stride;
256
257 filter_mbd->plane[2].pre[1].buf =
258 block_start(denoiser->running_avg_y[frame].v_buffer,
259 denoiser->running_avg_y[frame].uv_stride,
260 mi_row, mi_col);
261 filter_mbd->plane[2].pre[1].stride = denoiser->running_avg_y[frame].uv_stride;
262
263 filter_mbd->plane[0].dst.buf =
264 block_start(denoiser->mc_running_avg_y.y_buffer,
265 denoiser->mc_running_avg_y.y_stride,
266 mi_row, mi_col);
267 filter_mbd->plane[0].dst.stride = denoiser->mc_running_avg_y.y_stride;
268
269 filter_mbd->plane[1].dst.buf =
270 block_start(denoiser->mc_running_avg_y.u_buffer,
271 denoiser->mc_running_avg_y.uv_stride,
272 mi_row, mi_col);
273 filter_mbd->plane[1].dst.stride = denoiser->mc_running_avg_y.y_stride;
274
275 filter_mbd->plane[2].dst.buf =
276 block_start(denoiser->mc_running_avg_y.v_buffer,
277 denoiser->mc_running_avg_y.uv_stride,
278 mi_row, mi_col);
279 filter_mbd->plane[2].dst.stride = denoiser->mc_running_avg_y.y_stride;
280
281 vp9_build_inter_predictors_sby(filter_mbd, mv_row, mv_col, bs);
282
283 // Restore everything to its original state
284 filter_mbd->plane[0].pre[0] = saved_pre[0];
285 filter_mbd->plane[0].pre[1] = saved_pre[1];
286 filter_mbd->plane[0].dst = saved_dst;
287 *mbmi = saved_mbmi;
288
289 mv_row = denoiser->best_sse_mv.as_mv.row;
290 mv_col = denoiser->best_sse_mv.as_mv.col;
291
292 if (denoiser->best_sse > sse_thresh(bs, increase_denoising)) {
293 return COPY_BLOCK;
294 }
295 if (mv_row * mv_row + mv_col * mv_col >
296 8 * noise_motion_thresh(bs, increase_denoising)) {
297 return COPY_BLOCK;
298 }
299 return FILTER_BLOCK;
300 }
301
91 void vp9_denoiser_denoise(VP9_DENOISER *denoiser, MACROBLOCK *mb, 302 void vp9_denoiser_denoise(VP9_DENOISER *denoiser, MACROBLOCK *mb,
92 int mi_row, int mi_col, BLOCK_SIZE bs) { 303 int mi_row, int mi_col, BLOCK_SIZE bs) {
93 int decision = COPY_BLOCK; 304 VP9_DENOISER_DECISION decision = FILTER_BLOCK;
94
95 YV12_BUFFER_CONFIG avg = denoiser->running_avg_y[INTRA_FRAME]; 305 YV12_BUFFER_CONFIG avg = denoiser->running_avg_y[INTRA_FRAME];
306 YV12_BUFFER_CONFIG mc_avg = denoiser->mc_running_avg_y;
307 uint8_t *avg_start = block_start(avg.y_buffer, avg.y_stride, mi_row, mi_col);
308 uint8_t *mc_avg_start = block_start(mc_avg.y_buffer, mc_avg.y_stride,
309 mi_row, mi_col);
96 struct buf_2d src = mb->plane[0].src; 310 struct buf_2d src = mb->plane[0].src;
97 311
98 update_running_avg(denoiser->mc_running_avg_y.y_buffer, 312 decision = perform_motion_compensation(denoiser, mb, bs,
99 denoiser->mc_running_avg_y.y_stride, 313 denoiser->increase_denoising,
100 denoiser->running_avg_y[INTRA_FRAME].y_buffer, 314 mi_row, mi_col);
101 denoiser->running_avg_y[INTRA_FRAME].y_stride,
102 mb->plane[0].src.buf, mb->plane[0].src.stride, 0, bs);
103 315
104 if (decision == FILTER_BLOCK) { 316 if (decision == FILTER_BLOCK) {
105 // TODO(tkopp) 317 decision = denoiser_filter(src.buf, src.stride,
318 mc_avg_start, mc_avg.y_stride,
319 avg_start, avg.y_stride,
320 0, bs);
106 } 321 }
107 if (decision == COPY_BLOCK) { 322
108 copy_block(block_start(avg.y_buffer, avg.y_stride, mi_row, mi_col), 323 if (decision == FILTER_BLOCK) {
109 avg.y_stride, src.buf, src.stride, bs); 324 copy_block(src.buf, src.stride, avg_start, avg.y_stride, bs);
325 } else { // COPY_BLOCK
326 copy_block(avg_start, avg.y_stride, src.buf, src.stride, bs);
110 } 327 }
111 } 328 }
112 329
113 static void copy_frame(YV12_BUFFER_CONFIG dest, const YV12_BUFFER_CONFIG src) { 330 static void copy_frame(YV12_BUFFER_CONFIG dest, const YV12_BUFFER_CONFIG src) {
114 int r, c; 331 int r;
115 const uint8_t *srcbuf = src.y_buffer; 332 const uint8_t *srcbuf = src.y_buffer;
116 uint8_t *destbuf = dest.y_buffer; 333 uint8_t *destbuf = dest.y_buffer;
117 assert(dest.y_width == src.y_width); 334 assert(dest.y_width == src.y_width);
118 assert(dest.y_height == src.y_height); 335 assert(dest.y_height == src.y_height);
119 336
120 for (r = 0; r < dest.y_height; ++r) { 337 for (r = 0; r < dest.y_height; ++r) {
121 for (c = 0; c < dest.y_width; ++c) { 338 vpx_memcpy(destbuf, srcbuf, dest.y_width);
122 destbuf[c] = srcbuf[c];
123 }
124 destbuf += dest.y_stride; 339 destbuf += dest.y_stride;
125 srcbuf += src.y_stride; 340 srcbuf += src.y_stride;
126 } 341 }
127 } 342 }
128 343
129 void vp9_denoiser_update_frame_info(VP9_DENOISER *denoiser, 344 void vp9_denoiser_update_frame_info(VP9_DENOISER *denoiser,
130 YV12_BUFFER_CONFIG src, 345 YV12_BUFFER_CONFIG src,
131 FRAME_TYPE frame_type, 346 FRAME_TYPE frame_type,
132 int refresh_alt_ref_frame, 347 int refresh_alt_ref_frame,
133 int refresh_golden_frame, 348 int refresh_golden_frame,
(...skipping 14 matching lines...) Expand all
148 copy_frame(denoiser->running_avg_y[GOLDEN_FRAME], 363 copy_frame(denoiser->running_avg_y[GOLDEN_FRAME],
149 denoiser->running_avg_y[INTRA_FRAME]); 364 denoiser->running_avg_y[INTRA_FRAME]);
150 } 365 }
151 if (refresh_last_frame) { 366 if (refresh_last_frame) {
152 copy_frame(denoiser->running_avg_y[LAST_FRAME], 367 copy_frame(denoiser->running_avg_y[LAST_FRAME],
153 denoiser->running_avg_y[INTRA_FRAME]); 368 denoiser->running_avg_y[INTRA_FRAME]);
154 } 369 }
155 } 370 }
156 } 371 }
157 372
158 void vp9_denoiser_update_frame_stats() { 373 void vp9_denoiser_reset_frame_stats(VP9_DENOISER *denoiser) {
374 denoiser->zero_mv_sse = UINT_MAX;
375 denoiser->best_sse = UINT_MAX;
376 }
377
378 void vp9_denoiser_update_frame_stats(VP9_DENOISER *denoiser, MB_MODE_INFO *mbmi,
379 unsigned int sse, PREDICTION_MODE mode) {
380 // TODO(tkopp): Use both MVs if possible
381 if (mbmi->mv[0].as_int == 0 && sse < denoiser->zero_mv_sse) {
382 denoiser->zero_mv_sse = sse;
383 denoiser->best_zeromv_reference_frame = mbmi->ref_frame[0];
384 }
385
386 if (mbmi->mv[0].as_int != 0 && sse < denoiser->best_sse) {
387 denoiser->best_sse = sse;
388 denoiser->best_sse_inter_mode = mode;
389 denoiser->best_sse_mv = mbmi->mv[0];
390 denoiser->best_reference_frame = mbmi->ref_frame[0];
391 }
159 } 392 }
160 393
161 int vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height, 394 int vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height,
162 int ssx, int ssy, int border) { 395 int ssx, int ssy, int border) {
163 int i, fail; 396 int i, fail;
164 assert(denoiser != NULL); 397 assert(denoiser != NULL);
165 398
166 for (i = 0; i < MAX_REF_FRAMES; ++i) { 399 for (i = 0; i < MAX_REF_FRAMES; ++i) {
167 fail = vp9_alloc_frame_buffer(&denoiser->running_avg_y[i], width, height, 400 fail = vp9_alloc_frame_buffer(&denoiser->running_avg_y[i], width, height,
168 ssx, ssy, border); 401 ssx, ssy, border);
169 if (fail) { 402 if (fail) {
170 vp9_denoiser_free(denoiser); 403 vp9_denoiser_free(denoiser);
171 return 1; 404 return 1;
172 } 405 }
406 #ifdef OUTPUT_YUV_DENOISED
407 make_grayscale(&denoiser->running_avg_y[i]);
408 #endif
173 } 409 }
174 410
175 fail = vp9_alloc_frame_buffer(&denoiser->mc_running_avg_y, width, height, 411 fail = vp9_alloc_frame_buffer(&denoiser->mc_running_avg_y, width, height,
176 ssx, ssy, border); 412 ssx, ssy, border);
177 if (fail) { 413 if (fail) {
178 vp9_denoiser_free(denoiser); 414 vp9_denoiser_free(denoiser);
179 return 1; 415 return 1;
180 } 416 }
417 #ifdef OUTPUT_YUV_DENOISED
418 make_grayscale(&denoiser->running_avg_y[i]);
419 #endif
420 denoiser->increase_denoising = 0;
181 421
182 return 0; 422 return 0;
183 } 423 }
184 424
185 void vp9_denoiser_free(VP9_DENOISER *denoiser) { 425 void vp9_denoiser_free(VP9_DENOISER *denoiser) {
186 int i; 426 int i;
187 if (denoiser == NULL) { 427 if (denoiser == NULL) {
188 return; 428 return;
189 } 429 }
190 for (i = 0; i < MAX_REF_FRAMES; ++i) { 430 for (i = 0; i < MAX_REF_FRAMES; ++i) {
191 if (&denoiser->running_avg_y[i] != NULL) { 431 if (&denoiser->running_avg_y[i] != NULL) {
192 vp9_free_frame_buffer(&denoiser->running_avg_y[i]); 432 vp9_free_frame_buffer(&denoiser->running_avg_y[i]);
193 } 433 }
194 } 434 }
195 if (&denoiser->mc_running_avg_y != NULL) { 435 if (&denoiser->mc_running_avg_y != NULL) {
196 vp9_free_frame_buffer(&denoiser->mc_running_avg_y); 436 vp9_free_frame_buffer(&denoiser->mc_running_avg_y);
197 } 437 }
198 } 438 }
439
440 #ifdef OUTPUT_YUV_DENOISED
441 static void make_grayscale(YV12_BUFFER_CONFIG *yuv) {
442 int r, c;
443 uint8_t *u = yuv->u_buffer;
444 uint8_t *v = yuv->v_buffer;
445
446 // The '/2's are there because we have a 440 buffer, but we want to output
447 // 420.
448 for (r = 0; r < yuv->uv_height / 2; ++r) {
449 for (c = 0; c < yuv->uv_width / 2; ++c) {
450 u[c] = UINT8_MAX / 2;
451 v[c] = UINT8_MAX / 2;
452 }
453 u += yuv->uv_stride + yuv->uv_width / 2;
454 v += yuv->uv_stride + yuv->uv_width / 2;
455 }
456 }
457 #endif
OLDNEW
« no previous file with comments | « source/libvpx/vp9/encoder/vp9_denoiser.h ('k') | source/libvpx/vp9/encoder/vp9_encodeframe.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698