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/yv12config.h" 17 #include "vp9/common/vp9_postproc.h" 18 #include "vp9/common/vp9_textblit.h" 19 #include "vpx_scale/vpx_scale.h" 20 #include "vp9/common/vp9_systemdependent.h" 21 #include "./vp9_rtcd.h" 22 #include "./vpx_scale_rtcd.h" 23 24 #define RGB_TO_YUV(t) \ 25 ( (0.257*(float)(t >> 16)) + (0.504*(float)(t >> 8 & 0xff)) + \ 26 (0.098*(float)(t & 0xff)) + 16), \ 27 (-(0.148*(float)(t >> 16)) - (0.291*(float)(t >> 8 & 0xff)) + \ 28 (0.439*(float)(t & 0xff)) + 128), \ 29 ( (0.439*(float)(t >> 16)) - (0.368*(float)(t >> 8 & 0xff)) - \ 30 (0.071*(float)(t & 0xff)) + 128) 31 32 /* global constants */ 33 #if 0 && CONFIG_POSTPROC_VISUALIZER 34 static const unsigned char MB_PREDICTION_MODE_colors[MB_MODE_COUNT][3] = { 35 { RGB_TO_YUV(0x98FB98) }, /* PaleGreen */ 36 { RGB_TO_YUV(0x00FF00) }, /* Green */ 37 { RGB_TO_YUV(0xADFF2F) }, /* GreenYellow */ 38 { RGB_TO_YUV(0x8F0000) }, /* Dark Red */ 39 { RGB_TO_YUV(0x008F8F) }, /* Dark Cyan */ 40 { RGB_TO_YUV(0x008F8F) }, /* Dark Cyan */ 41 { RGB_TO_YUV(0x008F8F) }, /* Dark Cyan */ 42 { RGB_TO_YUV(0x8F0000) }, /* Dark Red */ 43 { RGB_TO_YUV(0x8F0000) }, /* Dark Red */ 44 { RGB_TO_YUV(0x228B22) }, /* ForestGreen */ 45 { RGB_TO_YUV(0x006400) }, /* DarkGreen */ 46 { RGB_TO_YUV(0x98F5FF) }, /* Cadet Blue */ 47 { RGB_TO_YUV(0x6CA6CD) }, /* Sky Blue */ 48 { RGB_TO_YUV(0x00008B) }, /* Dark blue */ 49 { RGB_TO_YUV(0x551A8B) }, /* Purple */ 50 { RGB_TO_YUV(0xFF0000) } /* Red */ 51 { RGB_TO_YUV(0xCC33FF) }, /* Magenta */ 52 }; 53 54 static const unsigned char B_PREDICTION_MODE_colors[INTRA_MODES][3] = { 55 { RGB_TO_YUV(0x6633ff) }, /* Purple */ 56 { RGB_TO_YUV(0xcc33ff) }, /* Magenta */ 57 { RGB_TO_YUV(0xff33cc) }, /* Pink */ 58 { RGB_TO_YUV(0xff3366) }, /* Coral */ 59 { RGB_TO_YUV(0x3366ff) }, /* Blue */ 60 { RGB_TO_YUV(0xed00f5) }, /* Dark Blue */ 61 { RGB_TO_YUV(0x2e00b8) }, /* Dark Purple */ 62 { RGB_TO_YUV(0xff6633) }, /* Orange */ 63 { RGB_TO_YUV(0x33ccff) }, /* Light Blue */ 64 { RGB_TO_YUV(0x8ab800) }, /* Green */ 65 { RGB_TO_YUV(0xffcc33) }, /* Light Orange */ 66 { RGB_TO_YUV(0x33ffcc) }, /* Aqua */ 67 { RGB_TO_YUV(0x66ff33) }, /* Light Green */ 68 { RGB_TO_YUV(0xccff33) }, /* Yellow */ 69 }; 70 71 static const unsigned char MV_REFERENCE_FRAME_colors[MAX_REF_FRAMES][3] = { 72 { RGB_TO_YUV(0x00ff00) }, /* Blue */ 73 { RGB_TO_YUV(0x0000ff) }, /* Green */ 74 { RGB_TO_YUV(0xffff00) }, /* Yellow */ 75 { RGB_TO_YUV(0xff0000) }, /* Red */ 76 }; 77 #endif 78 79 static const short kernel5[] = { 80 1, 1, 4, 1, 1 81 }; 82 83 const short vp9_rv[] = { 84 8, 5, 2, 2, 8, 12, 4, 9, 8, 3, 85 0, 3, 9, 0, 0, 0, 8, 3, 14, 4, 86 10, 1, 11, 14, 1, 14, 9, 6, 12, 11, 87 8, 6, 10, 0, 0, 8, 9, 0, 3, 14, 88 8, 11, 13, 4, 2, 9, 0, 3, 9, 6, 89 1, 2, 3, 14, 13, 1, 8, 2, 9, 7, 90 3, 3, 1, 13, 13, 6, 6, 5, 2, 7, 91 11, 9, 11, 8, 7, 3, 2, 0, 13, 13, 92 14, 4, 12, 5, 12, 10, 8, 10, 13, 10, 93 4, 14, 4, 10, 0, 8, 11, 1, 13, 7, 94 7, 14, 6, 14, 13, 2, 13, 5, 4, 4, 95 0, 10, 0, 5, 13, 2, 12, 7, 11, 13, 96 8, 0, 4, 10, 7, 2, 7, 2, 2, 5, 97 3, 4, 7, 3, 3, 14, 14, 5, 9, 13, 98 3, 14, 3, 6, 3, 0, 11, 8, 13, 1, 99 13, 1, 12, 0, 10, 9, 7, 6, 2, 8, 100 5, 2, 13, 7, 1, 13, 14, 7, 6, 7, 101 9, 6, 10, 11, 7, 8, 7, 5, 14, 8, 102 4, 4, 0, 8, 7, 10, 0, 8, 14, 11, 103 3, 12, 5, 7, 14, 3, 14, 5, 2, 6, 104 11, 12, 12, 8, 0, 11, 13, 1, 2, 0, 105 5, 10, 14, 7, 8, 0, 4, 11, 0, 8, 106 0, 3, 10, 5, 8, 0, 11, 6, 7, 8, 107 10, 7, 13, 9, 2, 5, 1, 5, 10, 2, 108 4, 3, 5, 6, 10, 8, 9, 4, 11, 14, 109 0, 10, 0, 5, 13, 2, 12, 7, 11, 13, 110 8, 0, 4, 10, 7, 2, 7, 2, 2, 5, 111 3, 4, 7, 3, 3, 14, 14, 5, 9, 13, 112 3, 14, 3, 6, 3, 0, 11, 8, 13, 1, 113 13, 1, 12, 0, 10, 9, 7, 6, 2, 8, 114 5, 2, 13, 7, 1, 13, 14, 7, 6, 7, 115 9, 6, 10, 11, 7, 8, 7, 5, 14, 8, 116 4, 4, 0, 8, 7, 10, 0, 8, 14, 11, 117 3, 12, 5, 7, 14, 3, 14, 5, 2, 6, 118 11, 12, 12, 8, 0, 11, 13, 1, 2, 0, 119 5, 10, 14, 7, 8, 0, 4, 11, 0, 8, 120 0, 3, 10, 5, 8, 0, 11, 6, 7, 8, 121 10, 7, 13, 9, 2, 5, 1, 5, 10, 2, 122 4, 3, 5, 6, 10, 8, 9, 4, 11, 14, 123 3, 8, 3, 7, 8, 5, 11, 4, 12, 3, 124 11, 9, 14, 8, 14, 13, 4, 3, 1, 2, 125 14, 6, 5, 4, 4, 11, 4, 6, 2, 1, 126 5, 8, 8, 12, 13, 5, 14, 10, 12, 13, 127 0, 9, 5, 5, 11, 10, 13, 9, 10, 13, 128 }; 129 130 131 /**************************************************************************** 132 */ 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 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 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 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 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 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 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 374 double vp9_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 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)(.5 + 256 * vp9_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 428 /**************************************************************************** 429 * 430 * ROUTINE : plane_add_noise_c 431 * 432 * INPUTS : unsigned char *Start starting address of buffer to 433 * add gaussian noise to 434 * unsigned int width width of plane 435 * unsigned int height height of plane 436 * int pitch distance between subsequent lines of frame 437 * int q quantizer used to determine amount of noise 438 * to add 439 * 440 * OUTPUTS : None. 441 * 442 * RETURNS : void. 443 * 444 * FUNCTION : adds gaussian noise to a plane of pixels 445 * 446 * SPECIAL NOTES : None. 447 * 448 ****************************************************************************/ 449 void vp9_plane_add_noise_c(uint8_t *start, char *noise, 450 char blackclamp[16], 451 char whiteclamp[16], 452 char bothclamp[16], 453 unsigned int width, unsigned int height, int pitch) { 454 unsigned int i, j; 455 456 for (i = 0; i < height; i++) { 457 uint8_t *pos = start + i * pitch; 458 char *ref = (char *)(noise + (rand() & 0xff)); // NOLINT 459 460 for (j = 0; j < width; j++) { 461 if (pos[j] < blackclamp[0]) 462 pos[j] = blackclamp[0]; 463 464 if (pos[j] > 255 + whiteclamp[0]) 465 pos[j] = 255 + whiteclamp[0]; 466 467 pos[j] += ref[j]; 468 } 469 } 470 } 471 472 /* Blend the macro block with a solid colored square. Leave the 473 * edges unblended to give distinction to macro blocks in areas 474 * filled with the same color block. 475 */ 476 void vp9_blend_mb_inner_c(uint8_t *y, uint8_t *u, uint8_t *v, 477 int y1, int u1, int v1, int alpha, int stride) { 478 int i, j; 479 int y1_const = y1 * ((1 << 16) - alpha); 480 int u1_const = u1 * ((1 << 16) - alpha); 481 int v1_const = v1 * ((1 << 16) - alpha); 482 483 y += 2 * stride + 2; 484 for (i = 0; i < 12; i++) { 485 for (j = 0; j < 12; j++) { 486 y[j] = (y[j] * alpha + y1_const) >> 16; 487 } 488 y += stride; 489 } 490 491 stride >>= 1; 492 493 u += stride + 1; 494 v += stride + 1; 495 496 for (i = 0; i < 6; i++) { 497 for (j = 0; j < 6; j++) { 498 u[j] = (u[j] * alpha + u1_const) >> 16; 499 v[j] = (v[j] * alpha + v1_const) >> 16; 500 } 501 u += stride; 502 v += stride; 503 } 504 } 505 506 /* Blend only the edge of the macro block. Leave center 507 * unblended to allow for other visualizations to be layered. 508 */ 509 void vp9_blend_mb_outer_c(uint8_t *y, uint8_t *u, uint8_t *v, 510 int y1, int u1, int v1, int alpha, int stride) { 511 int i, j; 512 int y1_const = y1 * ((1 << 16) - alpha); 513 int u1_const = u1 * ((1 << 16) - alpha); 514 int v1_const = v1 * ((1 << 16) - alpha); 515 516 for (i = 0; i < 2; i++) { 517 for (j = 0; j < 16; j++) { 518 y[j] = (y[j] * alpha + y1_const) >> 16; 519 } 520 y += stride; 521 } 522 523 for (i = 0; i < 12; i++) { 524 y[0] = (y[0] * alpha + y1_const) >> 16; 525 y[1] = (y[1] * alpha + y1_const) >> 16; 526 y[14] = (y[14] * alpha + y1_const) >> 16; 527 y[15] = (y[15] * alpha + y1_const) >> 16; 528 y += stride; 529 } 530 531 for (i = 0; i < 2; i++) { 532 for (j = 0; j < 16; j++) { 533 y[j] = (y[j] * alpha + y1_const) >> 16; 534 } 535 y += stride; 536 } 537 538 stride >>= 1; 539 540 for (j = 0; j < 8; j++) { 541 u[j] = (u[j] * alpha + u1_const) >> 16; 542 v[j] = (v[j] * alpha + v1_const) >> 16; 543 } 544 u += stride; 545 v += stride; 546 547 for (i = 0; i < 6; i++) { 548 u[0] = (u[0] * alpha + u1_const) >> 16; 549 v[0] = (v[0] * alpha + v1_const) >> 16; 550 551 u[7] = (u[7] * alpha + u1_const) >> 16; 552 v[7] = (v[7] * alpha + v1_const) >> 16; 553 554 u += stride; 555 v += stride; 556 } 557 558 for (j = 0; j < 8; j++) { 559 u[j] = (u[j] * alpha + u1_const) >> 16; 560 v[j] = (v[j] * alpha + v1_const) >> 16; 561 } 562 } 563 564 void vp9_blend_b_c(uint8_t *y, uint8_t *u, uint8_t *v, 565 int y1, int u1, int v1, int alpha, int stride) { 566 int i, j; 567 int y1_const = y1 * ((1 << 16) - alpha); 568 int u1_const = u1 * ((1 << 16) - alpha); 569 int v1_const = v1 * ((1 << 16) - alpha); 570 571 for (i = 0; i < 4; i++) { 572 for (j = 0; j < 4; j++) { 573 y[j] = (y[j] * alpha + y1_const) >> 16; 574 } 575 y += stride; 576 } 577 578 stride >>= 1; 579 580 for (i = 0; i < 2; i++) { 581 for (j = 0; j < 2; j++) { 582 u[j] = (u[j] * alpha + u1_const) >> 16; 583 v[j] = (v[j] * alpha + v1_const) >> 16; 584 } 585 u += stride; 586 v += stride; 587 } 588 } 589 590 static void constrain_line(int x0, int *x1, int y0, int *y1, 591 int width, int height) { 592 int dx; 593 int dy; 594 595 if (*x1 > width) { 596 dx = *x1 - x0; 597 dy = *y1 - y0; 598 599 *x1 = width; 600 if (dx) 601 *y1 = ((width - x0) * dy) / dx + y0; 602 } 603 if (*x1 < 0) { 604 dx = *x1 - x0; 605 dy = *y1 - y0; 606 607 *x1 = 0; 608 if (dx) 609 *y1 = ((0 - x0) * dy) / dx + y0; 610 } 611 if (*y1 > height) { 612 dx = *x1 - x0; 613 dy = *y1 - y0; 614 615 *y1 = height; 616 if (dy) 617 *x1 = ((height - y0) * dx) / dy + x0; 618 } 619 if (*y1 < 0) { 620 dx = *x1 - x0; 621 dy = *y1 - y0; 622 623 *y1 = 0; 624 if (dy) 625 *x1 = ((0 - y0) * dx) / dy + x0; 626 } 627 } 628 629 int vp9_post_proc_frame(struct VP9Common *cm, 630 YV12_BUFFER_CONFIG *dest, vp9_ppflags_t *ppflags) { 631 int q = cm->lf.filter_level * 10 / 6; 632 int flags = ppflags->post_proc_flag; 633 int deblock_level = ppflags->deblocking_level; 634 int noise_level = ppflags->noise_level; 635 636 if (!cm->frame_to_show) 637 return -1; 638 639 if (q > 63) 640 q = 63; 641 642 if (!flags) { 643 *dest = *cm->frame_to_show; 644 return 0; 645 } 646 647 #if ARCH_X86||ARCH_X86_64 648 vpx_reset_mmx_state(); 649 #endif 650 651 if (flags & VP9D_DEMACROBLOCK) { 652 deblock_and_de_macro_block(cm->frame_to_show, &cm->post_proc_buffer, 653 q + (deblock_level - 5) * 10, 1, 0); 654 } else if (flags & VP9D_DEBLOCK) { 655 vp9_deblock(cm->frame_to_show, &cm->post_proc_buffer, q); 656 } else { 657 vp8_yv12_copy_frame(cm->frame_to_show, &cm->post_proc_buffer); 658 } 659 660 if (flags & VP9D_ADDNOISE) { 661 if (cm->postproc_state.last_q != q 662 || cm->postproc_state.last_noise != noise_level) { 663 fillrd(&cm->postproc_state, 63 - q, noise_level); 664 } 665 666 vp9_plane_add_noise(cm->post_proc_buffer.y_buffer, 667 cm->postproc_state.noise, 668 cm->postproc_state.blackclamp, 669 cm->postproc_state.whiteclamp, 670 cm->postproc_state.bothclamp, 671 cm->post_proc_buffer.y_width, 672 cm->post_proc_buffer.y_height, 673 cm->post_proc_buffer.y_stride); 674 } 675 676 #if 0 && CONFIG_POSTPROC_VISUALIZER 677 if (flags & VP9D_DEBUG_TXT_FRAME_INFO) { 678 char message[512]; 679 snprintf(message, sizeof(message) -1, 680 "F%1dG%1dQ%3dF%3dP%d_s%dx%d", 681 (cm->frame_type == KEY_FRAME), 682 cm->refresh_golden_frame, 683 cm->base_qindex, 684 cm->filter_level, 685 flags, 686 cm->mb_cols, cm->mb_rows); 687 vp9_blit_text(message, cm->post_proc_buffer.y_buffer, 688 cm->post_proc_buffer.y_stride); 689 } 690 691 if (flags & VP9D_DEBUG_TXT_MBLK_MODES) { 692 int i, j; 693 uint8_t *y_ptr; 694 YV12_BUFFER_CONFIG *post = &cm->post_proc_buffer; 695 int mb_rows = post->y_height >> 4; 696 int mb_cols = post->y_width >> 4; 697 int mb_index = 0; 698 MODE_INFO *mi = cm->mi; 699 700 y_ptr = post->y_buffer + 4 * post->y_stride + 4; 701 702 /* vp9_filter each macro block */ 703 for (i = 0; i < mb_rows; i++) { 704 for (j = 0; j < mb_cols; j++) { 705 char zz[4]; 706 707 snprintf(zz, sizeof(zz) - 1, "%c", mi[mb_index].mbmi.mode + 'a'); 708 709 vp9_blit_text(zz, y_ptr, post->y_stride); 710 mb_index++; 711 y_ptr += 16; 712 } 713 714 mb_index++; /* border */ 715 y_ptr += post->y_stride * 16 - post->y_width; 716 } 717 } 718 719 if (flags & VP9D_DEBUG_TXT_DC_DIFF) { 720 int i, j; 721 uint8_t *y_ptr; 722 YV12_BUFFER_CONFIG *post = &cm->post_proc_buffer; 723 int mb_rows = post->y_height >> 4; 724 int mb_cols = post->y_width >> 4; 725 int mb_index = 0; 726 MODE_INFO *mi = cm->mi; 727 728 y_ptr = post->y_buffer + 4 * post->y_stride + 4; 729 730 /* vp9_filter each macro block */ 731 for (i = 0; i < mb_rows; i++) { 732 for (j = 0; j < mb_cols; j++) { 733 char zz[4]; 734 int dc_diff = !(mi[mb_index].mbmi.mode != I4X4_PRED && 735 mi[mb_index].mbmi.mode != SPLITMV && 736 mi[mb_index].mbmi.skip_coeff); 737 738 if (cm->frame_type == KEY_FRAME) 739 snprintf(zz, sizeof(zz) - 1, "a"); 740 else 741 snprintf(zz, sizeof(zz) - 1, "%c", dc_diff + '0'); 742 743 vp9_blit_text(zz, y_ptr, post->y_stride); 744 mb_index++; 745 y_ptr += 16; 746 } 747 748 mb_index++; /* border */ 749 y_ptr += post->y_stride * 16 - post->y_width; 750 } 751 } 752 753 if (flags & VP9D_DEBUG_TXT_RATE_INFO) { 754 char message[512]; 755 snprintf(message, sizeof(message), 756 "Bitrate: %10.2f framerate: %10.2f ", 757 cm->bitrate, cm->framerate); 758 vp9_blit_text(message, cm->post_proc_buffer.y_buffer, 759 cm->post_proc_buffer.y_stride); 760 } 761 762 /* Draw motion vectors */ 763 if ((flags & VP9D_DEBUG_DRAW_MV) && ppflags->display_mv_flag) { 764 YV12_BUFFER_CONFIG *post = &cm->post_proc_buffer; 765 int width = post->y_width; 766 int height = post->y_height; 767 uint8_t *y_buffer = cm->post_proc_buffer.y_buffer; 768 int y_stride = cm->post_proc_buffer.y_stride; 769 MODE_INFO *mi = cm->mi; 770 int x0, y0; 771 772 for (y0 = 0; y0 < height; y0 += 16) { 773 for (x0 = 0; x0 < width; x0 += 16) { 774 int x1, y1; 775 776 if (!(ppflags->display_mv_flag & (1 << mi->mbmi.mode))) { 777 mi++; 778 continue; 779 } 780 781 if (mi->mbmi.mode == SPLITMV) { 782 switch (mi->mbmi.partitioning) { 783 case PARTITIONING_16X8 : { /* mv_top_bottom */ 784 union b_mode_info *bmi = &mi->bmi[0]; 785 MV *mv = &bmi->mv.as_mv; 786 787 x1 = x0 + 8 + (mv->col >> 3); 788 y1 = y0 + 4 + (mv->row >> 3); 789 790 constrain_line(x0 + 8, &x1, y0 + 4, &y1, width, height); 791 vp9_blit_line(x0 + 8, x1, y0 + 4, y1, y_buffer, y_stride); 792 793 bmi = &mi->bmi[8]; 794 795 x1 = x0 + 8 + (mv->col >> 3); 796 y1 = y0 + 12 + (mv->row >> 3); 797 798 constrain_line(x0 + 8, &x1, y0 + 12, &y1, width, height); 799 vp9_blit_line(x0 + 8, x1, y0 + 12, y1, y_buffer, y_stride); 800 801 break; 802 } 803 case PARTITIONING_8X16 : { /* mv_left_right */ 804 union b_mode_info *bmi = &mi->bmi[0]; 805 MV *mv = &bmi->mv.as_mv; 806 807 x1 = x0 + 4 + (mv->col >> 3); 808 y1 = y0 + 8 + (mv->row >> 3); 809 810 constrain_line(x0 + 4, &x1, y0 + 8, &y1, width, height); 811 vp9_blit_line(x0 + 4, x1, y0 + 8, y1, y_buffer, y_stride); 812 813 bmi = &mi->bmi[2]; 814 815 x1 = x0 + 12 + (mv->col >> 3); 816 y1 = y0 + 8 + (mv->row >> 3); 817 818 constrain_line(x0 + 12, &x1, y0 + 8, &y1, width, height); 819 vp9_blit_line(x0 + 12, x1, y0 + 8, y1, y_buffer, y_stride); 820 821 break; 822 } 823 case PARTITIONING_8X8 : { /* mv_quarters */ 824 union b_mode_info *bmi = &mi->bmi[0]; 825 MV *mv = &bmi->mv.as_mv; 826 827 x1 = x0 + 4 + (mv->col >> 3); 828 y1 = y0 + 4 + (mv->row >> 3); 829 830 constrain_line(x0 + 4, &x1, y0 + 4, &y1, width, height); 831 vp9_blit_line(x0 + 4, x1, y0 + 4, y1, y_buffer, y_stride); 832 833 bmi = &mi->bmi[2]; 834 835 x1 = x0 + 12 + (mv->col >> 3); 836 y1 = y0 + 4 + (mv->row >> 3); 837 838 constrain_line(x0 + 12, &x1, y0 + 4, &y1, width, height); 839 vp9_blit_line(x0 + 12, x1, y0 + 4, y1, y_buffer, y_stride); 840 841 bmi = &mi->bmi[8]; 842 843 x1 = x0 + 4 + (mv->col >> 3); 844 y1 = y0 + 12 + (mv->row >> 3); 845 846 constrain_line(x0 + 4, &x1, y0 + 12, &y1, width, height); 847 vp9_blit_line(x0 + 4, x1, y0 + 12, y1, y_buffer, y_stride); 848 849 bmi = &mi->bmi[10]; 850 851 x1 = x0 + 12 + (mv->col >> 3); 852 y1 = y0 + 12 + (mv->row >> 3); 853 854 constrain_line(x0 + 12, &x1, y0 + 12, &y1, width, height); 855 vp9_blit_line(x0 + 12, x1, y0 + 12, y1, y_buffer, y_stride); 856 break; 857 } 858 case PARTITIONING_4X4: 859 default : { 860 union b_mode_info *bmi = mi->bmi; 861 int bx0, by0; 862 863 for (by0 = y0; by0 < (y0 + 16); by0 += 4) { 864 for (bx0 = x0; bx0 < (x0 + 16); bx0 += 4) { 865 MV *mv = &bmi->mv.as_mv; 866 867 x1 = bx0 + 2 + (mv->col >> 3); 868 y1 = by0 + 2 + (mv->row >> 3); 869 870 constrain_line(bx0 + 2, &x1, by0 + 2, &y1, width, height); 871 vp9_blit_line(bx0 + 2, x1, by0 + 2, y1, y_buffer, y_stride); 872 873 bmi++; 874 } 875 } 876 } 877 } 878 } else if (is_inter_mode(mi->mbmi.mode)) { 879 MV *mv = &mi->mbmi.mv.as_mv; 880 const int lx0 = x0 + 8; 881 const int ly0 = y0 + 8; 882 883 x1 = lx0 + (mv->col >> 3); 884 y1 = ly0 + (mv->row >> 3); 885 886 if (x1 != lx0 && y1 != ly0) { 887 constrain_line(lx0, &x1, ly0 - 1, &y1, width, height); 888 vp9_blit_line(lx0, x1, ly0 - 1, y1, y_buffer, y_stride); 889 890 constrain_line(lx0, &x1, ly0 + 1, &y1, width, height); 891 vp9_blit_line(lx0, x1, ly0 + 1, y1, y_buffer, y_stride); 892 } else { 893 vp9_blit_line(lx0, x1, ly0, y1, y_buffer, y_stride); 894 } 895 } 896 897 mi++; 898 } 899 mi++; 900 } 901 } 902 903 /* Color in block modes */ 904 if ((flags & VP9D_DEBUG_CLR_BLK_MODES) 905 && (ppflags->display_mb_modes_flag || ppflags->display_b_modes_flag)) { 906 int y, x; 907 YV12_BUFFER_CONFIG *post = &cm->post_proc_buffer; 908 int width = post->y_width; 909 int height = post->y_height; 910 uint8_t *y_ptr = cm->post_proc_buffer.y_buffer; 911 uint8_t *u_ptr = cm->post_proc_buffer.u_buffer; 912 uint8_t *v_ptr = cm->post_proc_buffer.v_buffer; 913 int y_stride = cm->post_proc_buffer.y_stride; 914 MODE_INFO *mi = cm->mi; 915 916 for (y = 0; y < height; y += 16) { 917 for (x = 0; x < width; x += 16) { 918 int Y = 0, U = 0, V = 0; 919 920 if (mi->mbmi.mode == I4X4_PRED && 921 ((ppflags->display_mb_modes_flag & I4X4_PRED) || 922 ppflags->display_b_modes_flag)) { 923 int by, bx; 924 uint8_t *yl, *ul, *vl; 925 union b_mode_info *bmi = mi->bmi; 926 927 yl = y_ptr + x; 928 ul = u_ptr + (x >> 1); 929 vl = v_ptr + (x >> 1); 930 931 for (by = 0; by < 16; by += 4) { 932 for (bx = 0; bx < 16; bx += 4) { 933 if ((ppflags->display_b_modes_flag & (1 << mi->mbmi.mode)) 934 || (ppflags->display_mb_modes_flag & I4X4_PRED)) { 935 Y = B_PREDICTION_MODE_colors[bmi->as_mode][0]; 936 U = B_PREDICTION_MODE_colors[bmi->as_mode][1]; 937 V = B_PREDICTION_MODE_colors[bmi->as_mode][2]; 938 939 vp9_blend_b(yl + bx, ul + (bx >> 1), vl + (bx >> 1), Y, U, V, 940 0xc000, y_stride); 941 } 942 bmi++; 943 } 944 945 yl += y_stride * 4; 946 ul += y_stride * 1; 947 vl += y_stride * 1; 948 } 949 } else if (ppflags->display_mb_modes_flag & (1 << mi->mbmi.mode)) { 950 Y = MB_PREDICTION_MODE_colors[mi->mbmi.mode][0]; 951 U = MB_PREDICTION_MODE_colors[mi->mbmi.mode][1]; 952 V = MB_PREDICTION_MODE_colors[mi->mbmi.mode][2]; 953 954 vp9_blend_mb_inner(y_ptr + x, u_ptr + (x >> 1), v_ptr + (x >> 1), 955 Y, U, V, 0xc000, y_stride); 956 } 957 958 mi++; 959 } 960 y_ptr += y_stride * 16; 961 u_ptr += y_stride * 4; 962 v_ptr += y_stride * 4; 963 964 mi++; 965 } 966 } 967 968 /* Color in frame reference blocks */ 969 if ((flags & VP9D_DEBUG_CLR_FRM_REF_BLKS) && 970 ppflags->display_ref_frame_flag) { 971 int y, x; 972 YV12_BUFFER_CONFIG *post = &cm->post_proc_buffer; 973 int width = post->y_width; 974 int height = post->y_height; 975 uint8_t *y_ptr = cm->post_proc_buffer.y_buffer; 976 uint8_t *u_ptr = cm->post_proc_buffer.u_buffer; 977 uint8_t *v_ptr = cm->post_proc_buffer.v_buffer; 978 int y_stride = cm->post_proc_buffer.y_stride; 979 MODE_INFO *mi = cm->mi; 980 981 for (y = 0; y < height; y += 16) { 982 for (x = 0; x < width; x += 16) { 983 int Y = 0, U = 0, V = 0; 984 985 if (ppflags->display_ref_frame_flag & (1 << mi->mbmi.ref_frame)) { 986 Y = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][0]; 987 U = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][1]; 988 V = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][2]; 989 990 vp9_blend_mb_outer(y_ptr + x, u_ptr + (x >> 1), v_ptr + (x >> 1), 991 Y, U, V, 0xc000, y_stride); 992 } 993 994 mi++; 995 } 996 y_ptr += y_stride * 16; 997 u_ptr += y_stride * 4; 998 v_ptr += y_stride * 4; 999 1000 mi++; 1001 } 1002 } 1003 #endif 1004 1005 *dest = cm->post_proc_buffer; 1006 1007 /* handle problem with extending borders */ 1008 dest->y_width = cm->width; 1009 dest->y_height = cm->height; 1010 dest->uv_width = dest->y_width >> cm->subsampling_x; 1011 dest->uv_height = dest->y_height >> cm->subsampling_y; 1012 1013 return 0; 1014 } 1015