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_rtcd.h" 14 #include "vpx_scale/yv12config.h" 15 #include "postproc.h" 16 #include "common.h" 17 #include "vpx_scale/vpxscale.h" 18 #include "systemdependent.h" 19 20 #include <limits.h> 21 #include <math.h> 22 #include <stdlib.h> 23 #include <stdio.h> 24 25 #define RGB_TO_YUV(t) \ 26 ( (0.257*(float)(t>>16)) + (0.504*(float)(t>>8&0xff)) + (0.098*(float)(t&0xff)) + 16), \ 27 (-(0.148*(float)(t>>16)) - (0.291*(float)(t>>8&0xff)) + (0.439*(float)(t&0xff)) + 128), \ 28 ( (0.439*(float)(t>>16)) - (0.368*(float)(t>>8&0xff)) - (0.071*(float)(t&0xff)) + 128) 29 30 /* global constants */ 31 #if CONFIG_POSTPROC_VISUALIZER 32 static const unsigned char MB_PREDICTION_MODE_colors[MB_MODE_COUNT][3] = 33 { 34 { RGB_TO_YUV(0x98FB98) }, /* PaleGreen */ 35 { RGB_TO_YUV(0x00FF00) }, /* Green */ 36 { RGB_TO_YUV(0xADFF2F) }, /* GreenYellow */ 37 { RGB_TO_YUV(0x228B22) }, /* ForestGreen */ 38 { RGB_TO_YUV(0x006400) }, /* DarkGreen */ 39 { RGB_TO_YUV(0x98F5FF) }, /* Cadet Blue */ 40 { RGB_TO_YUV(0x6CA6CD) }, /* Sky Blue */ 41 { RGB_TO_YUV(0x00008B) }, /* Dark blue */ 42 { RGB_TO_YUV(0x551A8B) }, /* Purple */ 43 { RGB_TO_YUV(0xFF0000) } /* Red */ 44 }; 45 46 static const unsigned char B_PREDICTION_MODE_colors[B_MODE_COUNT][3] = 47 { 48 { RGB_TO_YUV(0x6633ff) }, /* Purple */ 49 { RGB_TO_YUV(0xcc33ff) }, /* Magenta */ 50 { RGB_TO_YUV(0xff33cc) }, /* Pink */ 51 { RGB_TO_YUV(0xff3366) }, /* Coral */ 52 { RGB_TO_YUV(0x3366ff) }, /* Blue */ 53 { RGB_TO_YUV(0xed00f5) }, /* Dark Blue */ 54 { RGB_TO_YUV(0x2e00b8) }, /* Dark Purple */ 55 { RGB_TO_YUV(0xff6633) }, /* Orange */ 56 { RGB_TO_YUV(0x33ccff) }, /* Light Blue */ 57 { RGB_TO_YUV(0x8ab800) }, /* Green */ 58 { RGB_TO_YUV(0xffcc33) }, /* Light Orange */ 59 { RGB_TO_YUV(0x33ffcc) }, /* Aqua */ 60 { RGB_TO_YUV(0x66ff33) }, /* Light Green */ 61 { RGB_TO_YUV(0xccff33) }, /* Yellow */ 62 }; 63 64 static const unsigned char MV_REFERENCE_FRAME_colors[MAX_REF_FRAMES][3] = 65 { 66 { RGB_TO_YUV(0x00ff00) }, /* Blue */ 67 { RGB_TO_YUV(0x0000ff) }, /* Green */ 68 { RGB_TO_YUV(0xffff00) }, /* Yellow */ 69 { RGB_TO_YUV(0xff0000) }, /* Red */ 70 }; 71 #endif 72 73 static const short kernel5[] = 74 { 75 1, 1, 4, 1, 1 76 }; 77 78 const short vp8_rv[] = 79 { 80 8, 5, 2, 2, 8, 12, 4, 9, 8, 3, 81 0, 3, 9, 0, 0, 0, 8, 3, 14, 4, 82 10, 1, 11, 14, 1, 14, 9, 6, 12, 11, 83 8, 6, 10, 0, 0, 8, 9, 0, 3, 14, 84 8, 11, 13, 4, 2, 9, 0, 3, 9, 6, 85 1, 2, 3, 14, 13, 1, 8, 2, 9, 7, 86 3, 3, 1, 13, 13, 6, 6, 5, 2, 7, 87 11, 9, 11, 8, 7, 3, 2, 0, 13, 13, 88 14, 4, 12, 5, 12, 10, 8, 10, 13, 10, 89 4, 14, 4, 10, 0, 8, 11, 1, 13, 7, 90 7, 14, 6, 14, 13, 2, 13, 5, 4, 4, 91 0, 10, 0, 5, 13, 2, 12, 7, 11, 13, 92 8, 0, 4, 10, 7, 2, 7, 2, 2, 5, 93 3, 4, 7, 3, 3, 14, 14, 5, 9, 13, 94 3, 14, 3, 6, 3, 0, 11, 8, 13, 1, 95 13, 1, 12, 0, 10, 9, 7, 6, 2, 8, 96 5, 2, 13, 7, 1, 13, 14, 7, 6, 7, 97 9, 6, 10, 11, 7, 8, 7, 5, 14, 8, 98 4, 4, 0, 8, 7, 10, 0, 8, 14, 11, 99 3, 12, 5, 7, 14, 3, 14, 5, 2, 6, 100 11, 12, 12, 8, 0, 11, 13, 1, 2, 0, 101 5, 10, 14, 7, 8, 0, 4, 11, 0, 8, 102 0, 3, 10, 5, 8, 0, 11, 6, 7, 8, 103 10, 7, 13, 9, 2, 5, 1, 5, 10, 2, 104 4, 3, 5, 6, 10, 8, 9, 4, 11, 14, 105 0, 10, 0, 5, 13, 2, 12, 7, 11, 13, 106 8, 0, 4, 10, 7, 2, 7, 2, 2, 5, 107 3, 4, 7, 3, 3, 14, 14, 5, 9, 13, 108 3, 14, 3, 6, 3, 0, 11, 8, 13, 1, 109 13, 1, 12, 0, 10, 9, 7, 6, 2, 8, 110 5, 2, 13, 7, 1, 13, 14, 7, 6, 7, 111 9, 6, 10, 11, 7, 8, 7, 5, 14, 8, 112 4, 4, 0, 8, 7, 10, 0, 8, 14, 11, 113 3, 12, 5, 7, 14, 3, 14, 5, 2, 6, 114 11, 12, 12, 8, 0, 11, 13, 1, 2, 0, 115 5, 10, 14, 7, 8, 0, 4, 11, 0, 8, 116 0, 3, 10, 5, 8, 0, 11, 6, 7, 8, 117 10, 7, 13, 9, 2, 5, 1, 5, 10, 2, 118 4, 3, 5, 6, 10, 8, 9, 4, 11, 14, 119 3, 8, 3, 7, 8, 5, 11, 4, 12, 3, 120 11, 9, 14, 8, 14, 13, 4, 3, 1, 2, 121 14, 6, 5, 4, 4, 11, 4, 6, 2, 1, 122 5, 8, 8, 12, 13, 5, 14, 10, 12, 13, 123 0, 9, 5, 5, 11, 10, 13, 9, 10, 13, 124 }; 125 126 extern void vp8_blit_text(const char *msg, unsigned char *address, const int pitch); 127 extern void vp8_blit_line(int x0, int x1, int y0, int y1, unsigned char *image, const int pitch); 128 /*********************************************************************************************************** 129 */ 130 void vp8_post_proc_down_and_across_mb_row_c 131 ( 132 unsigned char *src_ptr, 133 unsigned char *dst_ptr, 134 int src_pixels_per_line, 135 int dst_pixels_per_line, 136 int cols, 137 unsigned char *f, 138 int size 139 ) 140 { 141 unsigned char *p_src, *p_dst; 142 int row; 143 int col; 144 unsigned char v; 145 unsigned char d[4]; 146 147 for (row = 0; row < size; row++) 148 { 149 /* post_proc_down for one row */ 150 p_src = src_ptr; 151 p_dst = dst_ptr; 152 153 for (col = 0; col < cols; col++) 154 { 155 unsigned char p_above2 = p_src[col - 2 * src_pixels_per_line]; 156 unsigned char p_above1 = p_src[col - src_pixels_per_line]; 157 unsigned char p_below1 = p_src[col + src_pixels_per_line]; 158 unsigned char p_below2 = p_src[col + 2 * src_pixels_per_line]; 159 160 v = p_src[col]; 161 162 if ((abs(v - p_above2) < f[col]) && (abs(v - p_above1) < f[col]) 163 && (abs(v - p_below1) < f[col]) && (abs(v - p_below2) < f[col])) 164 { 165 unsigned char k1, k2, k3; 166 k1 = (p_above2 + p_above1 + 1) >> 1; 167 k2 = (p_below2 + p_below1 + 1) >> 1; 168 k3 = (k1 + k2 + 1) >> 1; 169 v = (k3 + v + 1) >> 1; 170 } 171 172 p_dst[col] = v; 173 } 174 175 /* now post_proc_across */ 176 p_src = dst_ptr; 177 p_dst = dst_ptr; 178 179 p_src[-2] = p_src[-1] = p_src[0]; 180 p_src[cols] = p_src[cols + 1] = p_src[cols - 1]; 181 182 for (col = 0; col < cols; col++) 183 { 184 v = p_src[col]; 185 186 if ((abs(v - p_src[col - 2]) < f[col]) 187 && (abs(v - p_src[col - 1]) < f[col]) 188 && (abs(v - p_src[col + 1]) < f[col]) 189 && (abs(v - p_src[col + 2]) < f[col])) 190 { 191 unsigned char k1, k2, k3; 192 k1 = (p_src[col - 2] + p_src[col - 1] + 1) >> 1; 193 k2 = (p_src[col + 2] + p_src[col + 1] + 1) >> 1; 194 k3 = (k1 + k2 + 1) >> 1; 195 v = (k3 + v + 1) >> 1; 196 } 197 198 d[col & 3] = v; 199 200 if (col >= 2) 201 p_dst[col - 2] = d[(col - 2) & 3]; 202 } 203 204 /* handle the last two pixels */ 205 p_dst[col - 2] = d[(col - 2) & 3]; 206 p_dst[col - 1] = d[(col - 1) & 3]; 207 208 /* next row */ 209 src_ptr += src_pixels_per_line; 210 dst_ptr += dst_pixels_per_line; 211 } 212 } 213 214 static int q2mbl(int x) 215 { 216 if (x < 20) x = 20; 217 218 x = 50 + (x - 50) * 10 / 8; 219 return x * x / 3; 220 } 221 void vp8_mbpost_proc_across_ip_c(unsigned char *src, int pitch, int rows, int cols, int flimit) 222 { 223 int r, c, i; 224 225 unsigned char *s = src; 226 unsigned char d[16]; 227 228 for (r = 0; r < rows; r++) 229 { 230 int sumsq = 0; 231 int sum = 0; 232 233 for (i = -8; i<0; i++) 234 s[i]=s[0]; 235 236 /* 17 avoids valgrind warning - we buffer values in c in d 237 * and only write them when we've read 8 ahead... 238 */ 239 for (i = cols; i<cols+17; i++) 240 s[i]=s[cols-1]; 241 242 for (i = -8; i <= 6; i++) 243 { 244 sumsq += s[i] * s[i]; 245 sum += s[i]; 246 d[i+8] = 0; 247 } 248 249 for (c = 0; c < cols + 8; c++) 250 { 251 int x = s[c+7] - s[c-8]; 252 int y = s[c+7] + s[c-8]; 253 254 sum += x; 255 sumsq += x * y; 256 257 d[c&15] = s[c]; 258 259 if (sumsq * 15 - sum * sum < flimit) 260 { 261 d[c&15] = (8 + sum + s[c]) >> 4; 262 } 263 264 s[c-8] = d[(c-8)&15]; 265 } 266 267 s += pitch; 268 } 269 } 270 271 272 void vp8_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols, int flimit) 273 { 274 int r, c, i; 275 const short *rv3 = &vp8_rv[63&rand()]; 276 277 for (c = 0; c < cols; c++ ) 278 { 279 unsigned char *s = &dst[c]; 280 int sumsq = 0; 281 int sum = 0; 282 unsigned char d[16]; 283 const short *rv2 = rv3 + ((c * 17) & 127); 284 285 for (i = -8; i < 0; i++) 286 s[i*pitch]=s[0]; 287 288 /* 17 avoids valgrind warning - we buffer values in c in d 289 * and only write them when we've read 8 ahead... 290 */ 291 for (i = rows; i < rows+17; i++) 292 s[i*pitch]=s[(rows-1)*pitch]; 293 294 for (i = -8; i <= 6; i++) 295 { 296 sumsq += s[i*pitch] * s[i*pitch]; 297 sum += s[i*pitch]; 298 } 299 300 for (r = 0; r < rows + 8; r++) 301 { 302 sumsq += s[7*pitch] * s[ 7*pitch] - s[-8*pitch] * s[-8*pitch]; 303 sum += s[7*pitch] - s[-8*pitch]; 304 d[r&15] = s[0]; 305 306 if (sumsq * 15 - sum * sum < flimit) 307 { 308 d[r&15] = (rv2[r&127] + sum + s[0]) >> 4; 309 } 310 311 s[-8*pitch] = d[(r-8)&15]; 312 s += pitch; 313 } 314 } 315 } 316 317 static void vp8_de_mblock(YV12_BUFFER_CONFIG *post, 318 int q) 319 { 320 vp8_mbpost_proc_across_ip(post->y_buffer, post->y_stride, post->y_height, 321 post->y_width, q2mbl(q)); 322 vp8_mbpost_proc_down(post->y_buffer, post->y_stride, post->y_height, 323 post->y_width, q2mbl(q)); 324 } 325 326 void vp8_deblock(VP8_COMMON *cm, 327 YV12_BUFFER_CONFIG *source, 328 YV12_BUFFER_CONFIG *post, 329 int q, 330 int low_var_thresh, 331 int flag) 332 { 333 double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065; 334 int ppl = (int)(level + .5); 335 336 const MODE_INFO *mode_info_context = cm->mi; 337 int mbr, mbc; 338 339 /* The pixel thresholds are adjusted according to if or not the macroblock 340 * is a skipped block. */ 341 unsigned char *ylimits = cm->pp_limits_buffer; 342 unsigned char *uvlimits = cm->pp_limits_buffer + 16 * cm->mb_cols; 343 (void) low_var_thresh; 344 (void) flag; 345 346 if (ppl > 0) 347 { 348 for (mbr = 0; mbr < cm->mb_rows; mbr++) 349 { 350 unsigned char *ylptr = ylimits; 351 unsigned char *uvlptr = uvlimits; 352 for (mbc = 0; mbc < cm->mb_cols; mbc++) 353 { 354 unsigned char mb_ppl; 355 356 if (mode_info_context->mbmi.mb_skip_coeff) 357 mb_ppl = (unsigned char)ppl >> 1; 358 else 359 mb_ppl = (unsigned char)ppl; 360 361 vpx_memset(ylptr, mb_ppl, 16); 362 vpx_memset(uvlptr, mb_ppl, 8); 363 364 ylptr += 16; 365 uvlptr += 8; 366 mode_info_context++; 367 } 368 mode_info_context++; 369 370 vp8_post_proc_down_and_across_mb_row( 371 source->y_buffer + 16 * mbr * source->y_stride, 372 post->y_buffer + 16 * mbr * post->y_stride, source->y_stride, 373 post->y_stride, source->y_width, ylimits, 16); 374 375 vp8_post_proc_down_and_across_mb_row( 376 source->u_buffer + 8 * mbr * source->uv_stride, 377 post->u_buffer + 8 * mbr * post->uv_stride, source->uv_stride, 378 post->uv_stride, source->uv_width, uvlimits, 8); 379 vp8_post_proc_down_and_across_mb_row( 380 source->v_buffer + 8 * mbr * source->uv_stride, 381 post->v_buffer + 8 * mbr * post->uv_stride, source->uv_stride, 382 post->uv_stride, source->uv_width, uvlimits, 8); 383 } 384 } else 385 { 386 vp8_yv12_copy_frame(source, post); 387 } 388 } 389 390 #if !(CONFIG_TEMPORAL_DENOISING) 391 void vp8_de_noise(VP8_COMMON *cm, 392 YV12_BUFFER_CONFIG *source, 393 YV12_BUFFER_CONFIG *post, 394 int q, 395 int low_var_thresh, 396 int flag) 397 { 398 double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065; 399 int ppl = (int)(level + .5); 400 int mb_rows = source->y_width >> 4; 401 int mb_cols = source->y_height >> 4; 402 unsigned char *limits = cm->pp_limits_buffer;; 403 int mbr, mbc; 404 (void) post; 405 (void) low_var_thresh; 406 (void) flag; 407 408 vpx_memset(limits, (unsigned char)ppl, 16 * mb_cols); 409 410 /* TODO: The original code don't filter the 2 outer rows and columns. */ 411 for (mbr = 0; mbr < mb_rows; mbr++) 412 { 413 vp8_post_proc_down_and_across_mb_row( 414 source->y_buffer + 16 * mbr * source->y_stride, 415 source->y_buffer + 16 * mbr * source->y_stride, 416 source->y_stride, source->y_stride, source->y_width, limits, 16); 417 418 vp8_post_proc_down_and_across_mb_row( 419 source->u_buffer + 8 * mbr * source->uv_stride, 420 source->u_buffer + 8 * mbr * source->uv_stride, 421 source->uv_stride, source->uv_stride, source->uv_width, limits, 8); 422 vp8_post_proc_down_and_across_mb_row( 423 source->v_buffer + 8 * mbr * source->uv_stride, 424 source->v_buffer + 8 * mbr * source->uv_stride, 425 source->uv_stride, source->uv_stride, source->uv_width, limits, 8); 426 } 427 } 428 #endif 429 430 double vp8_gaussian(double sigma, double mu, double x) 431 { 432 return 1 / (sigma * sqrt(2.0 * 3.14159265)) * 433 (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma))); 434 } 435 436 static void fillrd(struct postproc_state *state, int q, int a) 437 { 438 char char_dist[300]; 439 440 double sigma; 441 int ai = a, qi = q, i; 442 443 vp8_clear_system_state(); 444 445 446 sigma = ai + .5 + .6 * (63 - qi) / 63.0; 447 448 /* set up a lookup table of 256 entries that matches 449 * a gaussian distribution with sigma determined by q. 450 */ 451 { 452 double i; 453 int next, j; 454 455 next = 0; 456 457 for (i = -32; i < 32; i++) 458 { 459 int a = (int)(.5 + 256 * vp8_gaussian(sigma, 0, i)); 460 461 if (a) 462 { 463 for (j = 0; j < a; j++) 464 { 465 char_dist[next+j] = (char) i; 466 } 467 468 next = next + j; 469 } 470 471 } 472 473 for (; next < 256; next++) 474 char_dist[next] = 0; 475 476 } 477 478 for (i = 0; i < 3072; i++) 479 { 480 state->noise[i] = char_dist[rand() & 0xff]; 481 } 482 483 for (i = 0; i < 16; i++) 484 { 485 state->blackclamp[i] = -char_dist[0]; 486 state->whiteclamp[i] = -char_dist[0]; 487 state->bothclamp[i] = -2 * char_dist[0]; 488 } 489 490 state->last_q = q; 491 state->last_noise = a; 492 } 493 494 /**************************************************************************** 495 * 496 * ROUTINE : plane_add_noise_c 497 * 498 * INPUTS : unsigned char *Start starting address of buffer to add gaussian 499 * noise to 500 * unsigned int Width width of plane 501 * unsigned int Height height of plane 502 * int Pitch distance between subsequent lines of frame 503 * int q quantizer used to determine amount of noise 504 * to add 505 * 506 * OUTPUTS : None. 507 * 508 * RETURNS : void. 509 * 510 * FUNCTION : adds gaussian noise to a plane of pixels 511 * 512 * SPECIAL NOTES : None. 513 * 514 ****************************************************************************/ 515 void vp8_plane_add_noise_c(unsigned char *Start, char *noise, 516 char blackclamp[16], 517 char whiteclamp[16], 518 char bothclamp[16], 519 unsigned int Width, unsigned int Height, int Pitch) 520 { 521 unsigned int i, j; 522 523 for (i = 0; i < Height; i++) 524 { 525 unsigned char *Pos = Start + i * Pitch; 526 char *Ref = (char *)(noise + (rand() & 0xff)); 527 528 for (j = 0; j < Width; j++) 529 { 530 if (Pos[j] < blackclamp[0]) 531 Pos[j] = blackclamp[0]; 532 533 if (Pos[j] > 255 + whiteclamp[0]) 534 Pos[j] = 255 + whiteclamp[0]; 535 536 Pos[j] += Ref[j]; 537 } 538 } 539 } 540 541 /* Blend the macro block with a solid colored square. Leave the 542 * edges unblended to give distinction to macro blocks in areas 543 * filled with the same color block. 544 */ 545 void vp8_blend_mb_inner_c (unsigned char *y, unsigned char *u, unsigned char *v, 546 int y1, int u1, int v1, int alpha, int stride) 547 { 548 int i, j; 549 int y1_const = y1*((1<<16)-alpha); 550 int u1_const = u1*((1<<16)-alpha); 551 int v1_const = v1*((1<<16)-alpha); 552 553 y += 2*stride + 2; 554 for (i = 0; i < 12; i++) 555 { 556 for (j = 0; j < 12; j++) 557 { 558 y[j] = (y[j]*alpha + y1_const)>>16; 559 } 560 y += stride; 561 } 562 563 stride >>= 1; 564 565 u += stride + 1; 566 v += stride + 1; 567 568 for (i = 0; i < 6; i++) 569 { 570 for (j = 0; j < 6; j++) 571 { 572 u[j] = (u[j]*alpha + u1_const)>>16; 573 v[j] = (v[j]*alpha + v1_const)>>16; 574 } 575 u += stride; 576 v += stride; 577 } 578 } 579 580 /* Blend only the edge of the macro block. Leave center 581 * unblended to allow for other visualizations to be layered. 582 */ 583 void vp8_blend_mb_outer_c (unsigned char *y, unsigned char *u, unsigned char *v, 584 int y1, int u1, int v1, int alpha, int stride) 585 { 586 int i, j; 587 int y1_const = y1*((1<<16)-alpha); 588 int u1_const = u1*((1<<16)-alpha); 589 int v1_const = v1*((1<<16)-alpha); 590 591 for (i = 0; i < 2; i++) 592 { 593 for (j = 0; j < 16; j++) 594 { 595 y[j] = (y[j]*alpha + y1_const)>>16; 596 } 597 y += stride; 598 } 599 600 for (i = 0; i < 12; i++) 601 { 602 y[0] = (y[0]*alpha + y1_const)>>16; 603 y[1] = (y[1]*alpha + y1_const)>>16; 604 y[14] = (y[14]*alpha + y1_const)>>16; 605 y[15] = (y[15]*alpha + y1_const)>>16; 606 y += stride; 607 } 608 609 for (i = 0; i < 2; i++) 610 { 611 for (j = 0; j < 16; j++) 612 { 613 y[j] = (y[j]*alpha + y1_const)>>16; 614 } 615 y += stride; 616 } 617 618 stride >>= 1; 619 620 for (j = 0; j < 8; j++) 621 { 622 u[j] = (u[j]*alpha + u1_const)>>16; 623 v[j] = (v[j]*alpha + v1_const)>>16; 624 } 625 u += stride; 626 v += stride; 627 628 for (i = 0; i < 6; i++) 629 { 630 u[0] = (u[0]*alpha + u1_const)>>16; 631 v[0] = (v[0]*alpha + v1_const)>>16; 632 633 u[7] = (u[7]*alpha + u1_const)>>16; 634 v[7] = (v[7]*alpha + v1_const)>>16; 635 636 u += stride; 637 v += stride; 638 } 639 640 for (j = 0; j < 8; j++) 641 { 642 u[j] = (u[j]*alpha + u1_const)>>16; 643 v[j] = (v[j]*alpha + v1_const)>>16; 644 } 645 } 646 647 void vp8_blend_b_c (unsigned char *y, unsigned char *u, unsigned char *v, 648 int y1, int u1, int v1, int alpha, int stride) 649 { 650 int i, j; 651 int y1_const = y1*((1<<16)-alpha); 652 int u1_const = u1*((1<<16)-alpha); 653 int v1_const = v1*((1<<16)-alpha); 654 655 for (i = 0; i < 4; i++) 656 { 657 for (j = 0; j < 4; j++) 658 { 659 y[j] = (y[j]*alpha + y1_const)>>16; 660 } 661 y += stride; 662 } 663 664 stride >>= 1; 665 666 for (i = 0; i < 2; i++) 667 { 668 for (j = 0; j < 2; j++) 669 { 670 u[j] = (u[j]*alpha + u1_const)>>16; 671 v[j] = (v[j]*alpha + v1_const)>>16; 672 } 673 u += stride; 674 v += stride; 675 } 676 } 677 678 static void constrain_line (int x0, int *x1, int y0, int *y1, int width, int height) 679 { 680 int dx; 681 int dy; 682 683 if (*x1 > width) 684 { 685 dx = *x1 - x0; 686 dy = *y1 - y0; 687 688 *x1 = width; 689 if (dx) 690 *y1 = ((width-x0)*dy)/dx + y0; 691 } 692 if (*x1 < 0) 693 { 694 dx = *x1 - x0; 695 dy = *y1 - y0; 696 697 *x1 = 0; 698 if (dx) 699 *y1 = ((0-x0)*dy)/dx + y0; 700 } 701 if (*y1 > height) 702 { 703 dx = *x1 - x0; 704 dy = *y1 - y0; 705 706 *y1 = height; 707 if (dy) 708 *x1 = ((height-y0)*dx)/dy + x0; 709 } 710 if (*y1 < 0) 711 { 712 dx = *x1 - x0; 713 dy = *y1 - y0; 714 715 *y1 = 0; 716 if (dy) 717 *x1 = ((0-y0)*dx)/dy + x0; 718 } 719 } 720 721 #if CONFIG_POSTPROC 722 int vp8_post_proc_frame(VP8_COMMON *oci, YV12_BUFFER_CONFIG *dest, vp8_ppflags_t *ppflags) 723 { 724 int q = oci->filter_level * 10 / 6; 725 int flags = ppflags->post_proc_flag; 726 int deblock_level = ppflags->deblocking_level; 727 int noise_level = ppflags->noise_level; 728 729 if (!oci->frame_to_show) 730 return -1; 731 732 if (q > 63) 733 q = 63; 734 735 if (!flags) 736 { 737 *dest = *oci->frame_to_show; 738 739 /* handle problem with extending borders */ 740 dest->y_width = oci->Width; 741 dest->y_height = oci->Height; 742 dest->uv_height = dest->y_height / 2; 743 oci->postproc_state.last_base_qindex = oci->base_qindex; 744 oci->postproc_state.last_frame_valid = 1; 745 return 0; 746 } 747 748 /* Allocate post_proc_buffer_int if needed */ 749 if ((flags & VP8D_MFQE) && !oci->post_proc_buffer_int_used) 750 { 751 if ((flags & VP8D_DEBLOCK) || (flags & VP8D_DEMACROBLOCK)) 752 { 753 int width = (oci->Width + 15) & ~15; 754 int height = (oci->Height + 15) & ~15; 755 756 if (vp8_yv12_alloc_frame_buffer(&oci->post_proc_buffer_int, 757 width, height, VP8BORDERINPIXELS)) 758 vpx_internal_error(&oci->error, VPX_CODEC_MEM_ERROR, 759 "Failed to allocate MFQE framebuffer"); 760 761 oci->post_proc_buffer_int_used = 1; 762 763 /* insure that postproc is set to all 0's so that post proc 764 * doesn't pull random data in from edge 765 */ 766 vpx_memset((&oci->post_proc_buffer_int)->buffer_alloc,128,(&oci->post_proc_buffer)->frame_size); 767 768 } 769 } 770 771 vp8_clear_system_state(); 772 773 if ((flags & VP8D_MFQE) && 774 oci->postproc_state.last_frame_valid && 775 oci->current_video_frame >= 2 && 776 oci->postproc_state.last_base_qindex < 60 && 777 oci->base_qindex - oci->postproc_state.last_base_qindex >= 20) 778 { 779 vp8_multiframe_quality_enhance(oci); 780 if (((flags & VP8D_DEBLOCK) || (flags & VP8D_DEMACROBLOCK)) && 781 oci->post_proc_buffer_int_used) 782 { 783 vp8_yv12_copy_frame(&oci->post_proc_buffer, &oci->post_proc_buffer_int); 784 if (flags & VP8D_DEMACROBLOCK) 785 { 786 vp8_deblock(oci, &oci->post_proc_buffer_int, &oci->post_proc_buffer, 787 q + (deblock_level - 5) * 10, 1, 0); 788 vp8_de_mblock(&oci->post_proc_buffer, 789 q + (deblock_level - 5) * 10); 790 } 791 else if (flags & VP8D_DEBLOCK) 792 { 793 vp8_deblock(oci, &oci->post_proc_buffer_int, &oci->post_proc_buffer, 794 q, 1, 0); 795 } 796 } 797 /* Move partially towards the base q of the previous frame */ 798 oci->postproc_state.last_base_qindex = (3*oci->postproc_state.last_base_qindex + oci->base_qindex)>>2; 799 } 800 else if (flags & VP8D_DEMACROBLOCK) 801 { 802 vp8_deblock(oci, oci->frame_to_show, &oci->post_proc_buffer, 803 q + (deblock_level - 5) * 10, 1, 0); 804 vp8_de_mblock(&oci->post_proc_buffer, q + (deblock_level - 5) * 10); 805 806 oci->postproc_state.last_base_qindex = oci->base_qindex; 807 } 808 else if (flags & VP8D_DEBLOCK) 809 { 810 vp8_deblock(oci, oci->frame_to_show, &oci->post_proc_buffer, 811 q, 1, 0); 812 oci->postproc_state.last_base_qindex = oci->base_qindex; 813 } 814 else 815 { 816 vp8_yv12_copy_frame(oci->frame_to_show, &oci->post_proc_buffer); 817 oci->postproc_state.last_base_qindex = oci->base_qindex; 818 } 819 oci->postproc_state.last_frame_valid = 1; 820 821 if (flags & VP8D_ADDNOISE) 822 { 823 if (oci->postproc_state.last_q != q 824 || oci->postproc_state.last_noise != noise_level) 825 { 826 fillrd(&oci->postproc_state, 63 - q, noise_level); 827 } 828 829 vp8_plane_add_noise 830 (oci->post_proc_buffer.y_buffer, 831 oci->postproc_state.noise, 832 oci->postproc_state.blackclamp, 833 oci->postproc_state.whiteclamp, 834 oci->postproc_state.bothclamp, 835 oci->post_proc_buffer.y_width, oci->post_proc_buffer.y_height, 836 oci->post_proc_buffer.y_stride); 837 } 838 839 #if CONFIG_POSTPROC_VISUALIZER 840 if (flags & VP8D_DEBUG_TXT_FRAME_INFO) 841 { 842 char message[512]; 843 sprintf(message, "F%1dG%1dQ%3dF%3dP%d_s%dx%d", 844 (oci->frame_type == KEY_FRAME), 845 oci->refresh_golden_frame, 846 oci->base_qindex, 847 oci->filter_level, 848 flags, 849 oci->mb_cols, oci->mb_rows); 850 vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride); 851 } 852 853 if (flags & VP8D_DEBUG_TXT_MBLK_MODES) 854 { 855 int i, j; 856 unsigned char *y_ptr; 857 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer; 858 int mb_rows = post->y_height >> 4; 859 int mb_cols = post->y_width >> 4; 860 int mb_index = 0; 861 MODE_INFO *mi = oci->mi; 862 863 y_ptr = post->y_buffer + 4 * post->y_stride + 4; 864 865 /* vp8_filter each macro block */ 866 for (i = 0; i < mb_rows; i++) 867 { 868 for (j = 0; j < mb_cols; j++) 869 { 870 char zz[4]; 871 872 sprintf(zz, "%c", mi[mb_index].mbmi.mode + 'a'); 873 874 vp8_blit_text(zz, y_ptr, post->y_stride); 875 mb_index ++; 876 y_ptr += 16; 877 } 878 879 mb_index ++; /* border */ 880 y_ptr += post->y_stride * 16 - post->y_width; 881 882 } 883 } 884 885 if (flags & VP8D_DEBUG_TXT_DC_DIFF) 886 { 887 int i, j; 888 unsigned char *y_ptr; 889 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer; 890 int mb_rows = post->y_height >> 4; 891 int mb_cols = post->y_width >> 4; 892 int mb_index = 0; 893 MODE_INFO *mi = oci->mi; 894 895 y_ptr = post->y_buffer + 4 * post->y_stride + 4; 896 897 /* vp8_filter each macro block */ 898 for (i = 0; i < mb_rows; i++) 899 { 900 for (j = 0; j < mb_cols; j++) 901 { 902 char zz[4]; 903 int dc_diff = !(mi[mb_index].mbmi.mode != B_PRED && 904 mi[mb_index].mbmi.mode != SPLITMV && 905 mi[mb_index].mbmi.mb_skip_coeff); 906 907 if (oci->frame_type == KEY_FRAME) 908 sprintf(zz, "a"); 909 else 910 sprintf(zz, "%c", dc_diff + '0'); 911 912 vp8_blit_text(zz, y_ptr, post->y_stride); 913 mb_index ++; 914 y_ptr += 16; 915 } 916 917 mb_index ++; /* border */ 918 y_ptr += post->y_stride * 16 - post->y_width; 919 920 } 921 } 922 923 if (flags & VP8D_DEBUG_TXT_RATE_INFO) 924 { 925 char message[512]; 926 sprintf(message, "Bitrate: %10.2f frame_rate: %10.2f ", oci->bitrate, oci->framerate); 927 vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride); 928 } 929 930 /* Draw motion vectors */ 931 if ((flags & VP8D_DEBUG_DRAW_MV) && ppflags->display_mv_flag) 932 { 933 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer; 934 int width = post->y_width; 935 int height = post->y_height; 936 unsigned char *y_buffer = oci->post_proc_buffer.y_buffer; 937 int y_stride = oci->post_proc_buffer.y_stride; 938 MODE_INFO *mi = oci->mi; 939 int x0, y0; 940 941 for (y0 = 0; y0 < height; y0 += 16) 942 { 943 for (x0 = 0; x0 < width; x0 += 16) 944 { 945 int x1, y1; 946 947 if (!(ppflags->display_mv_flag & (1<<mi->mbmi.mode))) 948 { 949 mi++; 950 continue; 951 } 952 953 if (mi->mbmi.mode == SPLITMV) 954 { 955 switch (mi->mbmi.partitioning) 956 { 957 case 0 : /* mv_top_bottom */ 958 { 959 union b_mode_info *bmi = &mi->bmi[0]; 960 MV *mv = &bmi->mv.as_mv; 961 962 x1 = x0 + 8 + (mv->col >> 3); 963 y1 = y0 + 4 + (mv->row >> 3); 964 965 constrain_line (x0+8, &x1, y0+4, &y1, width, height); 966 vp8_blit_line (x0+8, x1, y0+4, y1, y_buffer, y_stride); 967 968 bmi = &mi->bmi[8]; 969 970 x1 = x0 + 8 + (mv->col >> 3); 971 y1 = y0 +12 + (mv->row >> 3); 972 973 constrain_line (x0+8, &x1, y0+12, &y1, width, height); 974 vp8_blit_line (x0+8, x1, y0+12, y1, y_buffer, y_stride); 975 976 break; 977 } 978 case 1 : /* mv_left_right */ 979 { 980 union b_mode_info *bmi = &mi->bmi[0]; 981 MV *mv = &bmi->mv.as_mv; 982 983 x1 = x0 + 4 + (mv->col >> 3); 984 y1 = y0 + 8 + (mv->row >> 3); 985 986 constrain_line (x0+4, &x1, y0+8, &y1, width, height); 987 vp8_blit_line (x0+4, x1, y0+8, y1, y_buffer, y_stride); 988 989 bmi = &mi->bmi[2]; 990 991 x1 = x0 +12 + (mv->col >> 3); 992 y1 = y0 + 8 + (mv->row >> 3); 993 994 constrain_line (x0+12, &x1, y0+8, &y1, width, height); 995 vp8_blit_line (x0+12, x1, y0+8, y1, y_buffer, y_stride); 996 997 break; 998 } 999 case 2 : /* mv_quarters */ 1000 { 1001 union b_mode_info *bmi = &mi->bmi[0]; 1002 MV *mv = &bmi->mv.as_mv; 1003 1004 x1 = x0 + 4 + (mv->col >> 3); 1005 y1 = y0 + 4 + (mv->row >> 3); 1006 1007 constrain_line (x0+4, &x1, y0+4, &y1, width, height); 1008 vp8_blit_line (x0+4, x1, y0+4, y1, y_buffer, y_stride); 1009 1010 bmi = &mi->bmi[2]; 1011 1012 x1 = x0 +12 + (mv->col >> 3); 1013 y1 = y0 + 4 + (mv->row >> 3); 1014 1015 constrain_line (x0+12, &x1, y0+4, &y1, width, height); 1016 vp8_blit_line (x0+12, x1, y0+4, y1, y_buffer, y_stride); 1017 1018 bmi = &mi->bmi[8]; 1019 1020 x1 = x0 + 4 + (mv->col >> 3); 1021 y1 = y0 +12 + (mv->row >> 3); 1022 1023 constrain_line (x0+4, &x1, y0+12, &y1, width, height); 1024 vp8_blit_line (x0+4, x1, y0+12, y1, y_buffer, y_stride); 1025 1026 bmi = &mi->bmi[10]; 1027 1028 x1 = x0 +12 + (mv->col >> 3); 1029 y1 = y0 +12 + (mv->row >> 3); 1030 1031 constrain_line (x0+12, &x1, y0+12, &y1, width, height); 1032 vp8_blit_line (x0+12, x1, y0+12, y1, y_buffer, y_stride); 1033 break; 1034 } 1035 default : 1036 { 1037 union b_mode_info *bmi = mi->bmi; 1038 int bx0, by0; 1039 1040 for (by0 = y0; by0 < (y0+16); by0 += 4) 1041 { 1042 for (bx0 = x0; bx0 < (x0+16); bx0 += 4) 1043 { 1044 MV *mv = &bmi->mv.as_mv; 1045 1046 x1 = bx0 + 2 + (mv->col >> 3); 1047 y1 = by0 + 2 + (mv->row >> 3); 1048 1049 constrain_line (bx0+2, &x1, by0+2, &y1, width, height); 1050 vp8_blit_line (bx0+2, x1, by0+2, y1, y_buffer, y_stride); 1051 1052 bmi++; 1053 } 1054 } 1055 } 1056 } 1057 } 1058 else if (mi->mbmi.mode >= NEARESTMV) 1059 { 1060 MV *mv = &mi->mbmi.mv.as_mv; 1061 const int lx0 = x0 + 8; 1062 const int ly0 = y0 + 8; 1063 1064 x1 = lx0 + (mv->col >> 3); 1065 y1 = ly0 + (mv->row >> 3); 1066 1067 if (x1 != lx0 && y1 != ly0) 1068 { 1069 constrain_line (lx0, &x1, ly0-1, &y1, width, height); 1070 vp8_blit_line (lx0, x1, ly0-1, y1, y_buffer, y_stride); 1071 1072 constrain_line (lx0, &x1, ly0+1, &y1, width, height); 1073 vp8_blit_line (lx0, x1, ly0+1, y1, y_buffer, y_stride); 1074 } 1075 else 1076 vp8_blit_line (lx0, x1, ly0, y1, y_buffer, y_stride); 1077 } 1078 1079 mi++; 1080 } 1081 mi++; 1082 } 1083 } 1084 1085 /* Color in block modes */ 1086 if ((flags & VP8D_DEBUG_CLR_BLK_MODES) 1087 && (ppflags->display_mb_modes_flag || ppflags->display_b_modes_flag)) 1088 { 1089 int y, x; 1090 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer; 1091 int width = post->y_width; 1092 int height = post->y_height; 1093 unsigned char *y_ptr = oci->post_proc_buffer.y_buffer; 1094 unsigned char *u_ptr = oci->post_proc_buffer.u_buffer; 1095 unsigned char *v_ptr = oci->post_proc_buffer.v_buffer; 1096 int y_stride = oci->post_proc_buffer.y_stride; 1097 MODE_INFO *mi = oci->mi; 1098 1099 for (y = 0; y < height; y += 16) 1100 { 1101 for (x = 0; x < width; x += 16) 1102 { 1103 int Y = 0, U = 0, V = 0; 1104 1105 if (mi->mbmi.mode == B_PRED && 1106 ((ppflags->display_mb_modes_flag & B_PRED) || ppflags->display_b_modes_flag)) 1107 { 1108 int by, bx; 1109 unsigned char *yl, *ul, *vl; 1110 union b_mode_info *bmi = mi->bmi; 1111 1112 yl = y_ptr + x; 1113 ul = u_ptr + (x>>1); 1114 vl = v_ptr + (x>>1); 1115 1116 for (by = 0; by < 16; by += 4) 1117 { 1118 for (bx = 0; bx < 16; bx += 4) 1119 { 1120 if ((ppflags->display_b_modes_flag & (1<<mi->mbmi.mode)) 1121 || (ppflags->display_mb_modes_flag & B_PRED)) 1122 { 1123 Y = B_PREDICTION_MODE_colors[bmi->as_mode][0]; 1124 U = B_PREDICTION_MODE_colors[bmi->as_mode][1]; 1125 V = B_PREDICTION_MODE_colors[bmi->as_mode][2]; 1126 1127 vp8_blend_b 1128 (yl+bx, ul+(bx>>1), vl+(bx>>1), Y, U, V, 0xc000, y_stride); 1129 } 1130 bmi++; 1131 } 1132 1133 yl += y_stride*4; 1134 ul += y_stride*1; 1135 vl += y_stride*1; 1136 } 1137 } 1138 else if (ppflags->display_mb_modes_flag & (1<<mi->mbmi.mode)) 1139 { 1140 Y = MB_PREDICTION_MODE_colors[mi->mbmi.mode][0]; 1141 U = MB_PREDICTION_MODE_colors[mi->mbmi.mode][1]; 1142 V = MB_PREDICTION_MODE_colors[mi->mbmi.mode][2]; 1143 1144 vp8_blend_mb_inner 1145 (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride); 1146 } 1147 1148 mi++; 1149 } 1150 y_ptr += y_stride*16; 1151 u_ptr += y_stride*4; 1152 v_ptr += y_stride*4; 1153 1154 mi++; 1155 } 1156 } 1157 1158 /* Color in frame reference blocks */ 1159 if ((flags & VP8D_DEBUG_CLR_FRM_REF_BLKS) && ppflags->display_ref_frame_flag) 1160 { 1161 int y, x; 1162 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer; 1163 int width = post->y_width; 1164 int height = post->y_height; 1165 unsigned char *y_ptr = oci->post_proc_buffer.y_buffer; 1166 unsigned char *u_ptr = oci->post_proc_buffer.u_buffer; 1167 unsigned char *v_ptr = oci->post_proc_buffer.v_buffer; 1168 int y_stride = oci->post_proc_buffer.y_stride; 1169 MODE_INFO *mi = oci->mi; 1170 1171 for (y = 0; y < height; y += 16) 1172 { 1173 for (x = 0; x < width; x +=16) 1174 { 1175 int Y = 0, U = 0, V = 0; 1176 1177 if (ppflags->display_ref_frame_flag & (1<<mi->mbmi.ref_frame)) 1178 { 1179 Y = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][0]; 1180 U = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][1]; 1181 V = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][2]; 1182 1183 vp8_blend_mb_outer 1184 (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride); 1185 } 1186 1187 mi++; 1188 } 1189 y_ptr += y_stride*16; 1190 u_ptr += y_stride*4; 1191 v_ptr += y_stride*4; 1192 1193 mi++; 1194 } 1195 } 1196 #endif 1197 1198 *dest = oci->post_proc_buffer; 1199 1200 /* handle problem with extending borders */ 1201 dest->y_width = oci->Width; 1202 dest->y_height = oci->Height; 1203 dest->uv_height = dest->y_height / 2; 1204 return 0; 1205 } 1206 #endif 1207