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