1 /*
2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include <math.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14
15 #include "./vpx_config.h"
16 #include "./vpx_scale_rtcd.h"
17 #include "./vp9_rtcd.h"
18
19 #include "vpx_scale/vpx_scale.h"
20 #include "vpx_scale/yv12config.h"
21
22 #include "vp9/common/vp9_onyxc_int.h"
23 #include "vp9/common/vp9_postproc.h"
24 #include "vp9/common/vp9_systemdependent.h"
25 #include "vp9/common/vp9_textblit.h"
26
27 #define RGB_TO_YUV(t) \
28 ( (0.257*(float)(t >> 16)) + (0.504*(float)(t >> 8 & 0xff)) + \
29 (0.098*(float)(t & 0xff)) + 16), \
30 (-(0.148*(float)(t >> 16)) - (0.291*(float)(t >> 8 & 0xff)) + \
31 (0.439*(float)(t & 0xff)) + 128), \
32 ( (0.439*(float)(t >> 16)) - (0.368*(float)(t >> 8 & 0xff)) - \
33 (0.071*(float)(t & 0xff)) + 128)
34
35 /* global constants */
36 #if 0 && CONFIG_POSTPROC_VISUALIZER
37 static const unsigned char MB_PREDICTION_MODE_colors[MB_MODE_COUNT][3] = {
38 { RGB_TO_YUV(0x98FB98) }, /* PaleGreen */
39 { RGB_TO_YUV(0x00FF00) }, /* Green */
40 { RGB_TO_YUV(0xADFF2F) }, /* GreenYellow */
41 { RGB_TO_YUV(0x8F0000) }, /* Dark Red */
42 { RGB_TO_YUV(0x008F8F) }, /* Dark Cyan */
43 { RGB_TO_YUV(0x008F8F) }, /* Dark Cyan */
44 { RGB_TO_YUV(0x008F8F) }, /* Dark Cyan */
45 { RGB_TO_YUV(0x8F0000) }, /* Dark Red */
46 { RGB_TO_YUV(0x8F0000) }, /* Dark Red */
47 { RGB_TO_YUV(0x228B22) }, /* ForestGreen */
48 { RGB_TO_YUV(0x006400) }, /* DarkGreen */
49 { RGB_TO_YUV(0x98F5FF) }, /* Cadet Blue */
50 { RGB_TO_YUV(0x6CA6CD) }, /* Sky Blue */
51 { RGB_TO_YUV(0x00008B) }, /* Dark blue */
52 { RGB_TO_YUV(0x551A8B) }, /* Purple */
53 { RGB_TO_YUV(0xFF0000) } /* Red */
54 { RGB_TO_YUV(0xCC33FF) }, /* Magenta */
55 };
56
57 static const unsigned char B_PREDICTION_MODE_colors[INTRA_MODES][3] = {
58 { RGB_TO_YUV(0x6633ff) }, /* Purple */
59 { RGB_TO_YUV(0xcc33ff) }, /* Magenta */
60 { RGB_TO_YUV(0xff33cc) }, /* Pink */
61 { RGB_TO_YUV(0xff3366) }, /* Coral */
62 { RGB_TO_YUV(0x3366ff) }, /* Blue */
63 { RGB_TO_YUV(0xed00f5) }, /* Dark Blue */
64 { RGB_TO_YUV(0x2e00b8) }, /* Dark Purple */
65 { RGB_TO_YUV(0xff6633) }, /* Orange */
66 { RGB_TO_YUV(0x33ccff) }, /* Light Blue */
67 { RGB_TO_YUV(0x8ab800) }, /* Green */
68 { RGB_TO_YUV(0xffcc33) }, /* Light Orange */
69 { RGB_TO_YUV(0x33ffcc) }, /* Aqua */
70 { RGB_TO_YUV(0x66ff33) }, /* Light Green */
71 { RGB_TO_YUV(0xccff33) }, /* Yellow */
72 };
73
74 static const unsigned char MV_REFERENCE_FRAME_colors[MAX_REF_FRAMES][3] = {
75 { RGB_TO_YUV(0x00ff00) }, /* Blue */
76 { RGB_TO_YUV(0x0000ff) }, /* Green */
77 { RGB_TO_YUV(0xffff00) }, /* Yellow */
78 { RGB_TO_YUV(0xff0000) }, /* Red */
79 };
80 #endif
81
82 static const short kernel5[] = {
83 1, 1, 4, 1, 1
84 };
85
86 const short vp9_rv[] = {
87 8, 5, 2, 2, 8, 12, 4, 9, 8, 3,
88 0, 3, 9, 0, 0, 0, 8, 3, 14, 4,
89 10, 1, 11, 14, 1, 14, 9, 6, 12, 11,
90 8, 6, 10, 0, 0, 8, 9, 0, 3, 14,
91 8, 11, 13, 4, 2, 9, 0, 3, 9, 6,
92 1, 2, 3, 14, 13, 1, 8, 2, 9, 7,
93 3, 3, 1, 13, 13, 6, 6, 5, 2, 7,
94 11, 9, 11, 8, 7, 3, 2, 0, 13, 13,
95 14, 4, 12, 5, 12, 10, 8, 10, 13, 10,
96 4, 14, 4, 10, 0, 8, 11, 1, 13, 7,
97 7, 14, 6, 14, 13, 2, 13, 5, 4, 4,
98 0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
99 8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
100 3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
101 3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
102 13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
103 5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
104 9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
105 4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
106 3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
107 11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
108 5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
109 0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
110 10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
111 4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
112 0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
113 8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
114 3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
115 3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
116 13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
117 5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
118 9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
119 4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
120 3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
121 11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
122 5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
123 0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
124 10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
125 4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
126 3, 8, 3, 7, 8, 5, 11, 4, 12, 3,
127 11, 9, 14, 8, 14, 13, 4, 3, 1, 2,
128 14, 6, 5, 4, 4, 11, 4, 6, 2, 1,
129 5, 8, 8, 12, 13, 5, 14, 10, 12, 13,
130 0, 9, 5, 5, 11, 10, 13, 9, 10, 13,
131 };
132
vp9_post_proc_down_and_across_c(const uint8_t * src_ptr,uint8_t * dst_ptr,int src_pixels_per_line,int dst_pixels_per_line,int rows,int cols,int flimit)133 void vp9_post_proc_down_and_across_c(const uint8_t *src_ptr,
134 uint8_t *dst_ptr,
135 int src_pixels_per_line,
136 int dst_pixels_per_line,
137 int rows,
138 int cols,
139 int flimit) {
140 uint8_t const *p_src;
141 uint8_t *p_dst;
142 int row;
143 int col;
144 int i;
145 int v;
146 int pitch = src_pixels_per_line;
147 uint8_t d[8];
148 (void)dst_pixels_per_line;
149
150 for (row = 0; row < rows; row++) {
151 /* post_proc_down for one row */
152 p_src = src_ptr;
153 p_dst = dst_ptr;
154
155 for (col = 0; col < cols; col++) {
156 int kernel = 4;
157 int v = p_src[col];
158
159 for (i = -2; i <= 2; i++) {
160 if (abs(v - p_src[col + i * pitch]) > flimit)
161 goto down_skip_convolve;
162
163 kernel += kernel5[2 + i] * p_src[col + i * pitch];
164 }
165
166 v = (kernel >> 3);
167 down_skip_convolve:
168 p_dst[col] = v;
169 }
170
171 /* now post_proc_across */
172 p_src = dst_ptr;
173 p_dst = dst_ptr;
174
175 for (i = 0; i < 8; i++)
176 d[i] = p_src[i];
177
178 for (col = 0; col < cols; col++) {
179 int kernel = 4;
180 v = p_src[col];
181
182 d[col & 7] = v;
183
184 for (i = -2; i <= 2; i++) {
185 if (abs(v - p_src[col + i]) > flimit)
186 goto across_skip_convolve;
187
188 kernel += kernel5[2 + i] * p_src[col + i];
189 }
190
191 d[col & 7] = (kernel >> 3);
192 across_skip_convolve:
193
194 if (col >= 2)
195 p_dst[col - 2] = d[(col - 2) & 7];
196 }
197
198 /* handle the last two pixels */
199 p_dst[col - 2] = d[(col - 2) & 7];
200 p_dst[col - 1] = d[(col - 1) & 7];
201
202
203 /* next row */
204 src_ptr += pitch;
205 dst_ptr += pitch;
206 }
207 }
208
q2mbl(int x)209 static int q2mbl(int x) {
210 if (x < 20) x = 20;
211
212 x = 50 + (x - 50) * 10 / 8;
213 return x * x / 3;
214 }
215
vp9_mbpost_proc_across_ip_c(uint8_t * src,int pitch,int rows,int cols,int flimit)216 void vp9_mbpost_proc_across_ip_c(uint8_t *src, int pitch,
217 int rows, int cols, int flimit) {
218 int r, c, i;
219
220 uint8_t *s = src;
221 uint8_t d[16];
222
223
224 for (r = 0; r < rows; r++) {
225 int sumsq = 0;
226 int sum = 0;
227
228 for (i = -8; i <= 6; i++) {
229 sumsq += s[i] * s[i];
230 sum += s[i];
231 d[i + 8] = 0;
232 }
233
234 for (c = 0; c < cols + 8; c++) {
235 int x = s[c + 7] - s[c - 8];
236 int y = s[c + 7] + s[c - 8];
237
238 sum += x;
239 sumsq += x * y;
240
241 d[c & 15] = s[c];
242
243 if (sumsq * 15 - sum * sum < flimit) {
244 d[c & 15] = (8 + sum + s[c]) >> 4;
245 }
246
247 s[c - 8] = d[(c - 8) & 15];
248 }
249
250 s += pitch;
251 }
252 }
253
vp9_mbpost_proc_down_c(uint8_t * dst,int pitch,int rows,int cols,int flimit)254 void vp9_mbpost_proc_down_c(uint8_t *dst, int pitch,
255 int rows, int cols, int flimit) {
256 int r, c, i;
257 const short *rv3 = &vp9_rv[63 & rand()]; // NOLINT
258
259 for (c = 0; c < cols; c++) {
260 uint8_t *s = &dst[c];
261 int sumsq = 0;
262 int sum = 0;
263 uint8_t d[16];
264 const short *rv2 = rv3 + ((c * 17) & 127);
265
266 for (i = -8; i <= 6; i++) {
267 sumsq += s[i * pitch] * s[i * pitch];
268 sum += s[i * pitch];
269 }
270
271 for (r = 0; r < rows + 8; r++) {
272 sumsq += s[7 * pitch] * s[ 7 * pitch] - s[-8 * pitch] * s[-8 * pitch];
273 sum += s[7 * pitch] - s[-8 * pitch];
274 d[r & 15] = s[0];
275
276 if (sumsq * 15 - sum * sum < flimit) {
277 d[r & 15] = (rv2[r & 127] + sum + s[0]) >> 4;
278 }
279
280 s[-8 * pitch] = d[(r - 8) & 15];
281 s += pitch;
282 }
283 }
284 }
285
deblock_and_de_macro_block(YV12_BUFFER_CONFIG * source,YV12_BUFFER_CONFIG * post,int q,int low_var_thresh,int flag)286 static void deblock_and_de_macro_block(YV12_BUFFER_CONFIG *source,
287 YV12_BUFFER_CONFIG *post,
288 int q,
289 int low_var_thresh,
290 int flag) {
291 double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
292 int ppl = (int)(level + .5);
293 (void) low_var_thresh;
294 (void) flag;
295
296 vp9_post_proc_down_and_across(source->y_buffer, post->y_buffer,
297 source->y_stride, post->y_stride,
298 source->y_height, source->y_width, ppl);
299
300 vp9_mbpost_proc_across_ip(post->y_buffer, post->y_stride, post->y_height,
301 post->y_width, q2mbl(q));
302
303 vp9_mbpost_proc_down(post->y_buffer, post->y_stride, post->y_height,
304 post->y_width, q2mbl(q));
305
306 vp9_post_proc_down_and_across(source->u_buffer, post->u_buffer,
307 source->uv_stride, post->uv_stride,
308 source->uv_height, source->uv_width, ppl);
309 vp9_post_proc_down_and_across(source->v_buffer, post->v_buffer,
310 source->uv_stride, post->uv_stride,
311 source->uv_height, source->uv_width, ppl);
312 }
313
vp9_deblock(const YV12_BUFFER_CONFIG * src,YV12_BUFFER_CONFIG * dst,int q)314 void vp9_deblock(const YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst,
315 int q) {
316 const int ppl = (int)(6.0e-05 * q * q * q - 0.0067 * q * q + 0.306 * q
317 + 0.0065 + 0.5);
318 int i;
319
320 const uint8_t *const srcs[4] = {src->y_buffer, src->u_buffer, src->v_buffer,
321 src->alpha_buffer};
322 const int src_strides[4] = {src->y_stride, src->uv_stride, src->uv_stride,
323 src->alpha_stride};
324 const int src_widths[4] = {src->y_width, src->uv_width, src->uv_width,
325 src->alpha_width};
326 const int src_heights[4] = {src->y_height, src->uv_height, src->uv_height,
327 src->alpha_height};
328
329 uint8_t *const dsts[4] = {dst->y_buffer, dst->u_buffer, dst->v_buffer,
330 dst->alpha_buffer};
331 const int dst_strides[4] = {dst->y_stride, dst->uv_stride, dst->uv_stride,
332 dst->alpha_stride};
333
334 for (i = 0; i < MAX_MB_PLANE; ++i)
335 vp9_post_proc_down_and_across(srcs[i], dsts[i],
336 src_strides[i], dst_strides[i],
337 src_heights[i], src_widths[i], ppl);
338 }
339
vp9_denoise(const YV12_BUFFER_CONFIG * src,YV12_BUFFER_CONFIG * dst,int q)340 void vp9_denoise(const YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst,
341 int q) {
342 const int ppl = (int)(6.0e-05 * q * q * q - 0.0067 * q * q + 0.306 * q
343 + 0.0065 + 0.5);
344 int i;
345
346 const uint8_t *const srcs[4] = {src->y_buffer, src->u_buffer, src->v_buffer,
347 src->alpha_buffer};
348 const int src_strides[4] = {src->y_stride, src->uv_stride, src->uv_stride,
349 src->alpha_stride};
350 const int src_widths[4] = {src->y_width, src->uv_width, src->uv_width,
351 src->alpha_width};
352 const int src_heights[4] = {src->y_height, src->uv_height, src->uv_height,
353 src->alpha_height};
354
355 uint8_t *const dsts[4] = {dst->y_buffer, dst->u_buffer, dst->v_buffer,
356 dst->alpha_buffer};
357 const int dst_strides[4] = {dst->y_stride, dst->uv_stride, dst->uv_stride,
358 dst->alpha_stride};
359
360 for (i = 0; i < MAX_MB_PLANE; ++i) {
361 const int src_stride = src_strides[i];
362 const uint8_t *const src = srcs[i] + 2 * src_stride + 2;
363 const int src_width = src_widths[i] - 4;
364 const int src_height = src_heights[i] - 4;
365
366 const int dst_stride = dst_strides[i];
367 uint8_t *const dst = dsts[i] + 2 * dst_stride + 2;
368
369 vp9_post_proc_down_and_across(src, dst, src_stride, dst_stride,
370 src_height, src_width, ppl);
371 }
372 }
373
gaussian(double sigma,double mu,double x)374 static double gaussian(double sigma, double mu, double x) {
375 return 1 / (sigma * sqrt(2.0 * 3.14159265)) *
376 (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma)));
377 }
378
fillrd(struct postproc_state * state,int q,int a)379 static void fillrd(struct postproc_state *state, int q, int a) {
380 char char_dist[300];
381
382 double sigma;
383 int ai = a, qi = q, i;
384
385 vp9_clear_system_state();
386
387 sigma = ai + .5 + .6 * (63 - qi) / 63.0;
388
389 /* set up a lookup table of 256 entries that matches
390 * a gaussian distribution with sigma determined by q.
391 */
392 {
393 double i;
394 int next, j;
395
396 next = 0;
397
398 for (i = -32; i < 32; i++) {
399 int a = (int)(0.5 + 256 * gaussian(sigma, 0, i));
400
401 if (a) {
402 for (j = 0; j < a; j++) {
403 char_dist[next + j] = (char) i;
404 }
405
406 next = next + j;
407 }
408 }
409
410 for (; next < 256; next++)
411 char_dist[next] = 0;
412 }
413
414 for (i = 0; i < 3072; i++) {
415 state->noise[i] = char_dist[rand() & 0xff]; // NOLINT
416 }
417
418 for (i = 0; i < 16; i++) {
419 state->blackclamp[i] = -char_dist[0];
420 state->whiteclamp[i] = -char_dist[0];
421 state->bothclamp[i] = -2 * char_dist[0];
422 }
423
424 state->last_q = q;
425 state->last_noise = a;
426 }
427
vp9_plane_add_noise_c(uint8_t * start,char * noise,char blackclamp[16],char whiteclamp[16],char bothclamp[16],unsigned int width,unsigned int height,int pitch)428 void vp9_plane_add_noise_c(uint8_t *start, char *noise,
429 char blackclamp[16],
430 char whiteclamp[16],
431 char bothclamp[16],
432 unsigned int width, unsigned int height, int pitch) {
433 unsigned int i, j;
434
435 for (i = 0; i < height; i++) {
436 uint8_t *pos = start + i * pitch;
437 char *ref = (char *)(noise + (rand() & 0xff)); // NOLINT
438
439 for (j = 0; j < width; j++) {
440 if (pos[j] < blackclamp[0])
441 pos[j] = blackclamp[0];
442
443 if (pos[j] > 255 + whiteclamp[0])
444 pos[j] = 255 + whiteclamp[0];
445
446 pos[j] += ref[j];
447 }
448 }
449 }
450
451 /* Blend the macro block with a solid colored square. Leave the
452 * edges unblended to give distinction to macro blocks in areas
453 * filled with the same color block.
454 */
vp9_blend_mb_inner_c(uint8_t * y,uint8_t * u,uint8_t * v,int y1,int u1,int v1,int alpha,int stride)455 void vp9_blend_mb_inner_c(uint8_t *y, uint8_t *u, uint8_t *v,
456 int y1, int u1, int v1, int alpha, int stride) {
457 int i, j;
458 int y1_const = y1 * ((1 << 16) - alpha);
459 int u1_const = u1 * ((1 << 16) - alpha);
460 int v1_const = v1 * ((1 << 16) - alpha);
461
462 y += 2 * stride + 2;
463 for (i = 0; i < 12; i++) {
464 for (j = 0; j < 12; j++) {
465 y[j] = (y[j] * alpha + y1_const) >> 16;
466 }
467 y += stride;
468 }
469
470 stride >>= 1;
471
472 u += stride + 1;
473 v += stride + 1;
474
475 for (i = 0; i < 6; i++) {
476 for (j = 0; j < 6; j++) {
477 u[j] = (u[j] * alpha + u1_const) >> 16;
478 v[j] = (v[j] * alpha + v1_const) >> 16;
479 }
480 u += stride;
481 v += stride;
482 }
483 }
484
485 /* Blend only the edge of the macro block. Leave center
486 * unblended to allow for other visualizations to be layered.
487 */
vp9_blend_mb_outer_c(uint8_t * y,uint8_t * u,uint8_t * v,int y1,int u1,int v1,int alpha,int stride)488 void vp9_blend_mb_outer_c(uint8_t *y, uint8_t *u, uint8_t *v,
489 int y1, int u1, int v1, int alpha, int stride) {
490 int i, j;
491 int y1_const = y1 * ((1 << 16) - alpha);
492 int u1_const = u1 * ((1 << 16) - alpha);
493 int v1_const = v1 * ((1 << 16) - alpha);
494
495 for (i = 0; i < 2; i++) {
496 for (j = 0; j < 16; j++) {
497 y[j] = (y[j] * alpha + y1_const) >> 16;
498 }
499 y += stride;
500 }
501
502 for (i = 0; i < 12; i++) {
503 y[0] = (y[0] * alpha + y1_const) >> 16;
504 y[1] = (y[1] * alpha + y1_const) >> 16;
505 y[14] = (y[14] * alpha + y1_const) >> 16;
506 y[15] = (y[15] * alpha + y1_const) >> 16;
507 y += stride;
508 }
509
510 for (i = 0; i < 2; i++) {
511 for (j = 0; j < 16; j++) {
512 y[j] = (y[j] * alpha + y1_const) >> 16;
513 }
514 y += stride;
515 }
516
517 stride >>= 1;
518
519 for (j = 0; j < 8; j++) {
520 u[j] = (u[j] * alpha + u1_const) >> 16;
521 v[j] = (v[j] * alpha + v1_const) >> 16;
522 }
523 u += stride;
524 v += stride;
525
526 for (i = 0; i < 6; i++) {
527 u[0] = (u[0] * alpha + u1_const) >> 16;
528 v[0] = (v[0] * alpha + v1_const) >> 16;
529
530 u[7] = (u[7] * alpha + u1_const) >> 16;
531 v[7] = (v[7] * alpha + v1_const) >> 16;
532
533 u += stride;
534 v += stride;
535 }
536
537 for (j = 0; j < 8; j++) {
538 u[j] = (u[j] * alpha + u1_const) >> 16;
539 v[j] = (v[j] * alpha + v1_const) >> 16;
540 }
541 }
542
vp9_blend_b_c(uint8_t * y,uint8_t * u,uint8_t * v,int y1,int u1,int v1,int alpha,int stride)543 void vp9_blend_b_c(uint8_t *y, uint8_t *u, uint8_t *v,
544 int y1, int u1, int v1, int alpha, int stride) {
545 int i, j;
546 int y1_const = y1 * ((1 << 16) - alpha);
547 int u1_const = u1 * ((1 << 16) - alpha);
548 int v1_const = v1 * ((1 << 16) - alpha);
549
550 for (i = 0; i < 4; i++) {
551 for (j = 0; j < 4; j++) {
552 y[j] = (y[j] * alpha + y1_const) >> 16;
553 }
554 y += stride;
555 }
556
557 stride >>= 1;
558
559 for (i = 0; i < 2; i++) {
560 for (j = 0; j < 2; j++) {
561 u[j] = (u[j] * alpha + u1_const) >> 16;
562 v[j] = (v[j] * alpha + v1_const) >> 16;
563 }
564 u += stride;
565 v += stride;
566 }
567 }
568
constrain_line(int x0,int * x1,int y0,int * y1,int width,int height)569 static void constrain_line(int x0, int *x1, int y0, int *y1,
570 int width, int height) {
571 int dx;
572 int dy;
573
574 if (*x1 > width) {
575 dx = *x1 - x0;
576 dy = *y1 - y0;
577
578 *x1 = width;
579 if (dx)
580 *y1 = ((width - x0) * dy) / dx + y0;
581 }
582 if (*x1 < 0) {
583 dx = *x1 - x0;
584 dy = *y1 - y0;
585
586 *x1 = 0;
587 if (dx)
588 *y1 = ((0 - x0) * dy) / dx + y0;
589 }
590 if (*y1 > height) {
591 dx = *x1 - x0;
592 dy = *y1 - y0;
593
594 *y1 = height;
595 if (dy)
596 *x1 = ((height - y0) * dx) / dy + x0;
597 }
598 if (*y1 < 0) {
599 dx = *x1 - x0;
600 dy = *y1 - y0;
601
602 *y1 = 0;
603 if (dy)
604 *x1 = ((0 - y0) * dx) / dy + x0;
605 }
606 }
607
vp9_post_proc_frame(struct VP9Common * cm,YV12_BUFFER_CONFIG * dest,vp9_ppflags_t * ppflags)608 int vp9_post_proc_frame(struct VP9Common *cm,
609 YV12_BUFFER_CONFIG *dest, vp9_ppflags_t *ppflags) {
610 const int q = MIN(63, cm->lf.filter_level * 10 / 6);
611 const int flags = ppflags->post_proc_flag;
612 YV12_BUFFER_CONFIG *const ppbuf = &cm->post_proc_buffer;
613 struct postproc_state *const ppstate = &cm->postproc_state;
614
615 if (!cm->frame_to_show)
616 return -1;
617
618 if (!flags) {
619 *dest = *cm->frame_to_show;
620 return 0;
621 }
622
623 vp9_clear_system_state();
624
625 if (flags & VP9D_DEMACROBLOCK) {
626 deblock_and_de_macro_block(cm->frame_to_show, ppbuf,
627 q + (ppflags->deblocking_level - 5) * 10, 1, 0);
628 } else if (flags & VP9D_DEBLOCK) {
629 vp9_deblock(cm->frame_to_show, ppbuf, q);
630 } else {
631 vp8_yv12_copy_frame(cm->frame_to_show, ppbuf);
632 }
633
634 if (flags & VP9D_ADDNOISE) {
635 const int noise_level = ppflags->noise_level;
636 if (ppstate->last_q != q ||
637 ppstate->last_noise != noise_level) {
638 fillrd(ppstate, 63 - q, noise_level);
639 }
640
641 vp9_plane_add_noise(ppbuf->y_buffer, ppstate->noise, ppstate->blackclamp,
642 ppstate->whiteclamp, ppstate->bothclamp,
643 ppbuf->y_width, ppbuf->y_height, ppbuf->y_stride);
644 }
645
646 #if 0 && CONFIG_POSTPROC_VISUALIZER
647 if (flags & VP9D_DEBUG_TXT_FRAME_INFO) {
648 char message[512];
649 snprintf(message, sizeof(message) -1,
650 "F%1dG%1dQ%3dF%3dP%d_s%dx%d",
651 (cm->frame_type == KEY_FRAME),
652 cm->refresh_golden_frame,
653 cm->base_qindex,
654 cm->filter_level,
655 flags,
656 cm->mb_cols, cm->mb_rows);
657 vp9_blit_text(message, ppbuf->y_buffer, ppbuf->y_stride);
658 }
659
660 if (flags & VP9D_DEBUG_TXT_MBLK_MODES) {
661 int i, j;
662 uint8_t *y_ptr;
663 int mb_rows = ppbuf->y_height >> 4;
664 int mb_cols = ppbuf->y_width >> 4;
665 int mb_index = 0;
666 MODE_INFO *mi = cm->mi;
667
668 y_ptr = post->y_buffer + 4 * post->y_stride + 4;
669
670 /* vp9_filter each macro block */
671 for (i = 0; i < mb_rows; i++) {
672 for (j = 0; j < mb_cols; j++) {
673 char zz[4];
674
675 snprintf(zz, sizeof(zz) - 1, "%c", mi[mb_index].mbmi.mode + 'a');
676
677 vp9_blit_text(zz, y_ptr, post->y_stride);
678 mb_index++;
679 y_ptr += 16;
680 }
681
682 mb_index++; /* border */
683 y_ptr += post->y_stride * 16 - post->y_width;
684 }
685 }
686
687 if (flags & VP9D_DEBUG_TXT_DC_DIFF) {
688 int i, j;
689 uint8_t *y_ptr;
690 int mb_rows = ppbuf->y_height >> 4;
691 int mb_cols = ppbuf->y_width >> 4;
692 int mb_index = 0;
693 MODE_INFO *mi = cm->mi;
694
695 y_ptr = post->y_buffer + 4 * post->y_stride + 4;
696
697 /* vp9_filter each macro block */
698 for (i = 0; i < mb_rows; i++) {
699 for (j = 0; j < mb_cols; j++) {
700 char zz[4];
701 int dc_diff = !(mi[mb_index].mbmi.mode != I4X4_PRED &&
702 mi[mb_index].mbmi.mode != SPLITMV &&
703 mi[mb_index].mbmi.skip);
704
705 if (cm->frame_type == KEY_FRAME)
706 snprintf(zz, sizeof(zz) - 1, "a");
707 else
708 snprintf(zz, sizeof(zz) - 1, "%c", dc_diff + '0');
709
710 vp9_blit_text(zz, y_ptr, post->y_stride);
711 mb_index++;
712 y_ptr += 16;
713 }
714
715 mb_index++; /* border */
716 y_ptr += post->y_stride * 16 - post->y_width;
717 }
718 }
719
720 if (flags & VP9D_DEBUG_TXT_RATE_INFO) {
721 char message[512];
722 snprintf(message, sizeof(message),
723 "Bitrate: %10.2f framerate: %10.2f ",
724 cm->bitrate, cm->framerate);
725 vp9_blit_text(message, ppbuf->y_buffer, ppbuf->y_stride);
726 }
727
728 /* Draw motion vectors */
729 if ((flags & VP9D_DEBUG_DRAW_MV) && ppflags->display_mv_flag) {
730 int width = ppbuf->y_width;
731 int height = ppbuf->y_height;
732 uint8_t *y_buffer = ppbuf->y_buffer;
733 int y_stride = ppbuf->y_stride;
734 MODE_INFO *mi = cm->mi;
735 int x0, y0;
736
737 for (y0 = 0; y0 < height; y0 += 16) {
738 for (x0 = 0; x0 < width; x0 += 16) {
739 int x1, y1;
740
741 if (!(ppflags->display_mv_flag & (1 << mi->mbmi.mode))) {
742 mi++;
743 continue;
744 }
745
746 if (mi->mbmi.mode == SPLITMV) {
747 switch (mi->mbmi.partitioning) {
748 case PARTITIONING_16X8 : { /* mv_top_bottom */
749 union b_mode_info *bmi = &mi->bmi[0];
750 MV *mv = &bmi->mv.as_mv;
751
752 x1 = x0 + 8 + (mv->col >> 3);
753 y1 = y0 + 4 + (mv->row >> 3);
754
755 constrain_line(x0 + 8, &x1, y0 + 4, &y1, width, height);
756 vp9_blit_line(x0 + 8, x1, y0 + 4, y1, y_buffer, y_stride);
757
758 bmi = &mi->bmi[8];
759
760 x1 = x0 + 8 + (mv->col >> 3);
761 y1 = y0 + 12 + (mv->row >> 3);
762
763 constrain_line(x0 + 8, &x1, y0 + 12, &y1, width, height);
764 vp9_blit_line(x0 + 8, x1, y0 + 12, y1, y_buffer, y_stride);
765
766 break;
767 }
768 case PARTITIONING_8X16 : { /* mv_left_right */
769 union b_mode_info *bmi = &mi->bmi[0];
770 MV *mv = &bmi->mv.as_mv;
771
772 x1 = x0 + 4 + (mv->col >> 3);
773 y1 = y0 + 8 + (mv->row >> 3);
774
775 constrain_line(x0 + 4, &x1, y0 + 8, &y1, width, height);
776 vp9_blit_line(x0 + 4, x1, y0 + 8, y1, y_buffer, y_stride);
777
778 bmi = &mi->bmi[2];
779
780 x1 = x0 + 12 + (mv->col >> 3);
781 y1 = y0 + 8 + (mv->row >> 3);
782
783 constrain_line(x0 + 12, &x1, y0 + 8, &y1, width, height);
784 vp9_blit_line(x0 + 12, x1, y0 + 8, y1, y_buffer, y_stride);
785
786 break;
787 }
788 case PARTITIONING_8X8 : { /* mv_quarters */
789 union b_mode_info *bmi = &mi->bmi[0];
790 MV *mv = &bmi->mv.as_mv;
791
792 x1 = x0 + 4 + (mv->col >> 3);
793 y1 = y0 + 4 + (mv->row >> 3);
794
795 constrain_line(x0 + 4, &x1, y0 + 4, &y1, width, height);
796 vp9_blit_line(x0 + 4, x1, y0 + 4, y1, y_buffer, y_stride);
797
798 bmi = &mi->bmi[2];
799
800 x1 = x0 + 12 + (mv->col >> 3);
801 y1 = y0 + 4 + (mv->row >> 3);
802
803 constrain_line(x0 + 12, &x1, y0 + 4, &y1, width, height);
804 vp9_blit_line(x0 + 12, x1, y0 + 4, y1, y_buffer, y_stride);
805
806 bmi = &mi->bmi[8];
807
808 x1 = x0 + 4 + (mv->col >> 3);
809 y1 = y0 + 12 + (mv->row >> 3);
810
811 constrain_line(x0 + 4, &x1, y0 + 12, &y1, width, height);
812 vp9_blit_line(x0 + 4, x1, y0 + 12, y1, y_buffer, y_stride);
813
814 bmi = &mi->bmi[10];
815
816 x1 = x0 + 12 + (mv->col >> 3);
817 y1 = y0 + 12 + (mv->row >> 3);
818
819 constrain_line(x0 + 12, &x1, y0 + 12, &y1, width, height);
820 vp9_blit_line(x0 + 12, x1, y0 + 12, y1, y_buffer, y_stride);
821 break;
822 }
823 case PARTITIONING_4X4:
824 default : {
825 union b_mode_info *bmi = mi->bmi;
826 int bx0, by0;
827
828 for (by0 = y0; by0 < (y0 + 16); by0 += 4) {
829 for (bx0 = x0; bx0 < (x0 + 16); bx0 += 4) {
830 MV *mv = &bmi->mv.as_mv;
831
832 x1 = bx0 + 2 + (mv->col >> 3);
833 y1 = by0 + 2 + (mv->row >> 3);
834
835 constrain_line(bx0 + 2, &x1, by0 + 2, &y1, width, height);
836 vp9_blit_line(bx0 + 2, x1, by0 + 2, y1, y_buffer, y_stride);
837
838 bmi++;
839 }
840 }
841 }
842 }
843 } else if (is_inter_mode(mi->mbmi.mode)) {
844 MV *mv = &mi->mbmi.mv.as_mv;
845 const int lx0 = x0 + 8;
846 const int ly0 = y0 + 8;
847
848 x1 = lx0 + (mv->col >> 3);
849 y1 = ly0 + (mv->row >> 3);
850
851 if (x1 != lx0 && y1 != ly0) {
852 constrain_line(lx0, &x1, ly0 - 1, &y1, width, height);
853 vp9_blit_line(lx0, x1, ly0 - 1, y1, y_buffer, y_stride);
854
855 constrain_line(lx0, &x1, ly0 + 1, &y1, width, height);
856 vp9_blit_line(lx0, x1, ly0 + 1, y1, y_buffer, y_stride);
857 } else {
858 vp9_blit_line(lx0, x1, ly0, y1, y_buffer, y_stride);
859 }
860 }
861
862 mi++;
863 }
864 mi++;
865 }
866 }
867
868 /* Color in block modes */
869 if ((flags & VP9D_DEBUG_CLR_BLK_MODES)
870 && (ppflags->display_mb_modes_flag || ppflags->display_b_modes_flag)) {
871 int y, x;
872 int width = ppbuf->y_width;
873 int height = ppbuf->y_height;
874 uint8_t *y_ptr = ppbuf->y_buffer;
875 uint8_t *u_ptr = ppbuf->u_buffer;
876 uint8_t *v_ptr = ppbuf->v_buffer;
877 int y_stride = ppbuf->y_stride;
878 MODE_INFO *mi = cm->mi;
879
880 for (y = 0; y < height; y += 16) {
881 for (x = 0; x < width; x += 16) {
882 int Y = 0, U = 0, V = 0;
883
884 if (mi->mbmi.mode == I4X4_PRED &&
885 ((ppflags->display_mb_modes_flag & I4X4_PRED) ||
886 ppflags->display_b_modes_flag)) {
887 int by, bx;
888 uint8_t *yl, *ul, *vl;
889 union b_mode_info *bmi = mi->bmi;
890
891 yl = y_ptr + x;
892 ul = u_ptr + (x >> 1);
893 vl = v_ptr + (x >> 1);
894
895 for (by = 0; by < 16; by += 4) {
896 for (bx = 0; bx < 16; bx += 4) {
897 if ((ppflags->display_b_modes_flag & (1 << mi->mbmi.mode))
898 || (ppflags->display_mb_modes_flag & I4X4_PRED)) {
899 Y = B_PREDICTION_MODE_colors[bmi->as_mode][0];
900 U = B_PREDICTION_MODE_colors[bmi->as_mode][1];
901 V = B_PREDICTION_MODE_colors[bmi->as_mode][2];
902
903 vp9_blend_b(yl + bx, ul + (bx >> 1), vl + (bx >> 1), Y, U, V,
904 0xc000, y_stride);
905 }
906 bmi++;
907 }
908
909 yl += y_stride * 4;
910 ul += y_stride * 1;
911 vl += y_stride * 1;
912 }
913 } else if (ppflags->display_mb_modes_flag & (1 << mi->mbmi.mode)) {
914 Y = MB_PREDICTION_MODE_colors[mi->mbmi.mode][0];
915 U = MB_PREDICTION_MODE_colors[mi->mbmi.mode][1];
916 V = MB_PREDICTION_MODE_colors[mi->mbmi.mode][2];
917
918 vp9_blend_mb_inner(y_ptr + x, u_ptr + (x >> 1), v_ptr + (x >> 1),
919 Y, U, V, 0xc000, y_stride);
920 }
921
922 mi++;
923 }
924 y_ptr += y_stride * 16;
925 u_ptr += y_stride * 4;
926 v_ptr += y_stride * 4;
927
928 mi++;
929 }
930 }
931
932 /* Color in frame reference blocks */
933 if ((flags & VP9D_DEBUG_CLR_FRM_REF_BLKS) &&
934 ppflags->display_ref_frame_flag) {
935 int y, x;
936 int width = ppbuf->y_width;
937 int height = ppbuf->y_height;
938 uint8_t *y_ptr = ppbuf->y_buffer;
939 uint8_t *u_ptr = ppbuf->u_buffer;
940 uint8_t *v_ptr = ppbuf->v_buffer;
941 int y_stride = ppbuf->y_stride;
942 MODE_INFO *mi = cm->mi;
943
944 for (y = 0; y < height; y += 16) {
945 for (x = 0; x < width; x += 16) {
946 int Y = 0, U = 0, V = 0;
947
948 if (ppflags->display_ref_frame_flag & (1 << mi->mbmi.ref_frame)) {
949 Y = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][0];
950 U = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][1];
951 V = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][2];
952
953 vp9_blend_mb_outer(y_ptr + x, u_ptr + (x >> 1), v_ptr + (x >> 1),
954 Y, U, V, 0xc000, y_stride);
955 }
956
957 mi++;
958 }
959 y_ptr += y_stride * 16;
960 u_ptr += y_stride * 4;
961 v_ptr += y_stride * 4;
962
963 mi++;
964 }
965 }
966 #endif
967
968 *dest = *ppbuf;
969
970 /* handle problem with extending borders */
971 dest->y_width = cm->width;
972 dest->y_height = cm->height;
973 dest->uv_width = dest->y_width >> cm->subsampling_x;
974 dest->uv_height = dest->y_height >> cm->subsampling_y;
975
976 return 0;
977 }
978