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 "vp8_rtcd.h" 14 #include "vpx_scale_rtcd.h" 15 #include "vpx_scale/yv12config.h" 16 #include "postproc.h" 17 #include "common.h" 18 #include "vpx_scale/vpx_scale.h" 19 #include "systemdependent.h" 20 21 #include <limits.h> 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)) + (0.098*(float)(t&0xff)) + 16), \ 28 (-(0.148*(float)(t>>16)) - (0.291*(float)(t>>8&0xff)) + (0.439*(float)(t&0xff)) + 128), \ 29 ( (0.439*(float)(t>>16)) - (0.368*(float)(t>>8&0xff)) - (0.071*(float)(t&0xff)) + 128) 30 31 /* global constants */ 32 #if CONFIG_POSTPROC_VISUALIZER 33 static const unsigned char MB_PREDICTION_MODE_colors[MB_MODE_COUNT][3] = 34 { 35 { RGB_TO_YUV(0x98FB98) }, /* PaleGreen */ 36 { RGB_TO_YUV(0x00FF00) }, /* Green */ 37 { RGB_TO_YUV(0xADFF2F) }, /* GreenYellow */ 38 { RGB_TO_YUV(0x228B22) }, /* ForestGreen */ 39 { RGB_TO_YUV(0x006400) }, /* DarkGreen */ 40 { RGB_TO_YUV(0x98F5FF) }, /* Cadet Blue */ 41 { RGB_TO_YUV(0x6CA6CD) }, /* Sky Blue */ 42 { RGB_TO_YUV(0x00008B) }, /* Dark blue */ 43 { RGB_TO_YUV(0x551A8B) }, /* Purple */ 44 { RGB_TO_YUV(0xFF0000) } /* Red */ 45 }; 46 47 static const unsigned char B_PREDICTION_MODE_colors[B_MODE_COUNT][3] = 48 { 49 { RGB_TO_YUV(0x6633ff) }, /* Purple */ 50 { RGB_TO_YUV(0xcc33ff) }, /* Magenta */ 51 { RGB_TO_YUV(0xff33cc) }, /* Pink */ 52 { RGB_TO_YUV(0xff3366) }, /* Coral */ 53 { RGB_TO_YUV(0x3366ff) }, /* Blue */ 54 { RGB_TO_YUV(0xed00f5) }, /* Dark Blue */ 55 { RGB_TO_YUV(0x2e00b8) }, /* Dark Purple */ 56 { RGB_TO_YUV(0xff6633) }, /* Orange */ 57 { RGB_TO_YUV(0x33ccff) }, /* Light Blue */ 58 { RGB_TO_YUV(0x8ab800) }, /* Green */ 59 { RGB_TO_YUV(0xffcc33) }, /* Light Orange */ 60 { RGB_TO_YUV(0x33ffcc) }, /* Aqua */ 61 { RGB_TO_YUV(0x66ff33) }, /* Light Green */ 62 { RGB_TO_YUV(0xccff33) }, /* Yellow */ 63 }; 64 65 static const unsigned char MV_REFERENCE_FRAME_colors[MAX_REF_FRAMES][3] = 66 { 67 { RGB_TO_YUV(0x00ff00) }, /* Blue */ 68 { RGB_TO_YUV(0x0000ff) }, /* Green */ 69 { RGB_TO_YUV(0xffff00) }, /* Yellow */ 70 { RGB_TO_YUV(0xff0000) }, /* Red */ 71 }; 72 #endif 73 74 static const short kernel5[] = 75 { 76 1, 1, 4, 1, 1 77 }; 78 79 const short vp8_rv[] = 80 { 81 8, 5, 2, 2, 8, 12, 4, 9, 8, 3, 82 0, 3, 9, 0, 0, 0, 8, 3, 14, 4, 83 10, 1, 11, 14, 1, 14, 9, 6, 12, 11, 84 8, 6, 10, 0, 0, 8, 9, 0, 3, 14, 85 8, 11, 13, 4, 2, 9, 0, 3, 9, 6, 86 1, 2, 3, 14, 13, 1, 8, 2, 9, 7, 87 3, 3, 1, 13, 13, 6, 6, 5, 2, 7, 88 11, 9, 11, 8, 7, 3, 2, 0, 13, 13, 89 14, 4, 12, 5, 12, 10, 8, 10, 13, 10, 90 4, 14, 4, 10, 0, 8, 11, 1, 13, 7, 91 7, 14, 6, 14, 13, 2, 13, 5, 4, 4, 92 0, 10, 0, 5, 13, 2, 12, 7, 11, 13, 93 8, 0, 4, 10, 7, 2, 7, 2, 2, 5, 94 3, 4, 7, 3, 3, 14, 14, 5, 9, 13, 95 3, 14, 3, 6, 3, 0, 11, 8, 13, 1, 96 13, 1, 12, 0, 10, 9, 7, 6, 2, 8, 97 5, 2, 13, 7, 1, 13, 14, 7, 6, 7, 98 9, 6, 10, 11, 7, 8, 7, 5, 14, 8, 99 4, 4, 0, 8, 7, 10, 0, 8, 14, 11, 100 3, 12, 5, 7, 14, 3, 14, 5, 2, 6, 101 11, 12, 12, 8, 0, 11, 13, 1, 2, 0, 102 5, 10, 14, 7, 8, 0, 4, 11, 0, 8, 103 0, 3, 10, 5, 8, 0, 11, 6, 7, 8, 104 10, 7, 13, 9, 2, 5, 1, 5, 10, 2, 105 4, 3, 5, 6, 10, 8, 9, 4, 11, 14, 106 0, 10, 0, 5, 13, 2, 12, 7, 11, 13, 107 8, 0, 4, 10, 7, 2, 7, 2, 2, 5, 108 3, 4, 7, 3, 3, 14, 14, 5, 9, 13, 109 3, 14, 3, 6, 3, 0, 11, 8, 13, 1, 110 13, 1, 12, 0, 10, 9, 7, 6, 2, 8, 111 5, 2, 13, 7, 1, 13, 14, 7, 6, 7, 112 9, 6, 10, 11, 7, 8, 7, 5, 14, 8, 113 4, 4, 0, 8, 7, 10, 0, 8, 14, 11, 114 3, 12, 5, 7, 14, 3, 14, 5, 2, 6, 115 11, 12, 12, 8, 0, 11, 13, 1, 2, 0, 116 5, 10, 14, 7, 8, 0, 4, 11, 0, 8, 117 0, 3, 10, 5, 8, 0, 11, 6, 7, 8, 118 10, 7, 13, 9, 2, 5, 1, 5, 10, 2, 119 4, 3, 5, 6, 10, 8, 9, 4, 11, 14, 120 3, 8, 3, 7, 8, 5, 11, 4, 12, 3, 121 11, 9, 14, 8, 14, 13, 4, 3, 1, 2, 122 14, 6, 5, 4, 4, 11, 4, 6, 2, 1, 123 5, 8, 8, 12, 13, 5, 14, 10, 12, 13, 124 0, 9, 5, 5, 11, 10, 13, 9, 10, 13, 125 }; 126 127 extern void vp8_blit_text(const char *msg, unsigned char *address, const int pitch); 128 extern void vp8_blit_line(int x0, int x1, int y0, int y1, unsigned char *image, const int pitch); 129 /*********************************************************************************************************** 130 */ 131 void vp8_post_proc_down_and_across_mb_row_c 132 ( 133 unsigned char *src_ptr, 134 unsigned char *dst_ptr, 135 int src_pixels_per_line, 136 int dst_pixels_per_line, 137 int cols, 138 unsigned char *f, 139 int size 140 ) 141 { 142 unsigned char *p_src, *p_dst; 143 int row; 144 int col; 145 unsigned char v; 146 unsigned char d[4]; 147 148 for (row = 0; row < size; row++) 149 { 150 /* post_proc_down for one row */ 151 p_src = src_ptr; 152 p_dst = dst_ptr; 153 154 for (col = 0; col < cols; col++) 155 { 156 unsigned char p_above2 = p_src[col - 2 * src_pixels_per_line]; 157 unsigned char p_above1 = p_src[col - src_pixels_per_line]; 158 unsigned char p_below1 = p_src[col + src_pixels_per_line]; 159 unsigned char p_below2 = p_src[col + 2 * src_pixels_per_line]; 160 161 v = p_src[col]; 162 163 if ((abs(v - p_above2) < f[col]) && (abs(v - p_above1) < f[col]) 164 && (abs(v - p_below1) < f[col]) && (abs(v - p_below2) < f[col])) 165 { 166 unsigned char k1, k2, k3; 167 k1 = (p_above2 + p_above1 + 1) >> 1; 168 k2 = (p_below2 + p_below1 + 1) >> 1; 169 k3 = (k1 + k2 + 1) >> 1; 170 v = (k3 + v + 1) >> 1; 171 } 172 173 p_dst[col] = v; 174 } 175 176 /* now post_proc_across */ 177 p_src = dst_ptr; 178 p_dst = dst_ptr; 179 180 p_src[-2] = p_src[-1] = p_src[0]; 181 p_src[cols] = p_src[cols + 1] = p_src[cols - 1]; 182 183 for (col = 0; col < cols; col++) 184 { 185 v = p_src[col]; 186 187 if ((abs(v - p_src[col - 2]) < f[col]) 188 && (abs(v - p_src[col - 1]) < f[col]) 189 && (abs(v - p_src[col + 1]) < f[col]) 190 && (abs(v - p_src[col + 2]) < f[col])) 191 { 192 unsigned char k1, k2, k3; 193 k1 = (p_src[col - 2] + p_src[col - 1] + 1) >> 1; 194 k2 = (p_src[col + 2] + p_src[col + 1] + 1) >> 1; 195 k3 = (k1 + k2 + 1) >> 1; 196 v = (k3 + v + 1) >> 1; 197 } 198 199 d[col & 3] = v; 200 201 if (col >= 2) 202 p_dst[col - 2] = d[(col - 2) & 3]; 203 } 204 205 /* handle the last two pixels */ 206 p_dst[col - 2] = d[(col - 2) & 3]; 207 p_dst[col - 1] = d[(col - 1) & 3]; 208 209 /* next row */ 210 src_ptr += src_pixels_per_line; 211 dst_ptr += dst_pixels_per_line; 212 } 213 } 214 215 static int q2mbl(int x) 216 { 217 if (x < 20) x = 20; 218 219 x = 50 + (x - 50) * 10 / 8; 220 return x * x / 3; 221 } 222 void vp8_mbpost_proc_across_ip_c(unsigned char *src, int pitch, int rows, int cols, int flimit) 223 { 224 int r, c, i; 225 226 unsigned char *s = src; 227 unsigned char d[16]; 228 229 for (r = 0; r < rows; r++) 230 { 231 int sumsq = 0; 232 int sum = 0; 233 234 for (i = -8; i<0; i++) 235 s[i]=s[0]; 236 237 /* 17 avoids valgrind warning - we buffer values in c in d 238 * and only write them when we've read 8 ahead... 239 */ 240 for (i = cols; i<cols+17; i++) 241 s[i]=s[cols-1]; 242 243 for (i = -8; i <= 6; i++) 244 { 245 sumsq += s[i] * s[i]; 246 sum += s[i]; 247 d[i+8] = 0; 248 } 249 250 for (c = 0; c < cols + 8; c++) 251 { 252 int x = s[c+7] - s[c-8]; 253 int y = s[c+7] + s[c-8]; 254 255 sum += x; 256 sumsq += x * y; 257 258 d[c&15] = s[c]; 259 260 if (sumsq * 15 - sum * sum < flimit) 261 { 262 d[c&15] = (8 + sum + s[c]) >> 4; 263 } 264 265 s[c-8] = d[(c-8)&15]; 266 } 267 268 s += pitch; 269 } 270 } 271 272 273 void vp8_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols, int flimit) 274 { 275 int r, c, i; 276 const short *rv3 = &vp8_rv[63&rand()]; 277 278 for (c = 0; c < cols; c++ ) 279 { 280 unsigned char *s = &dst[c]; 281 int sumsq = 0; 282 int sum = 0; 283 unsigned char d[16]; 284 const short *rv2 = rv3 + ((c * 17) & 127); 285 286 for (i = -8; i < 0; i++) 287 s[i*pitch]=s[0]; 288 289 /* 17 avoids valgrind warning - we buffer values in c in d 290 * and only write them when we've read 8 ahead... 291 */ 292 for (i = rows; i < rows+17; i++) 293 s[i*pitch]=s[(rows-1)*pitch]; 294 295 for (i = -8; i <= 6; i++) 296 { 297 sumsq += s[i*pitch] * s[i*pitch]; 298 sum += s[i*pitch]; 299 } 300 301 for (r = 0; r < rows + 8; r++) 302 { 303 sumsq += s[7*pitch] * s[ 7*pitch] - s[-8*pitch] * s[-8*pitch]; 304 sum += s[7*pitch] - s[-8*pitch]; 305 d[r&15] = s[0]; 306 307 if (sumsq * 15 - sum * sum < flimit) 308 { 309 d[r&15] = (rv2[r&127] + sum + s[0]) >> 4; 310 } 311 312 s[-8*pitch] = d[(r-8)&15]; 313 s += pitch; 314 } 315 } 316 } 317 318 static void vp8_de_mblock(YV12_BUFFER_CONFIG *post, 319 int q) 320 { 321 vp8_mbpost_proc_across_ip(post->y_buffer, post->y_stride, post->y_height, 322 post->y_width, q2mbl(q)); 323 vp8_mbpost_proc_down(post->y_buffer, post->y_stride, post->y_height, 324 post->y_width, q2mbl(q)); 325 } 326 327 void vp8_deblock(VP8_COMMON *cm, 328 YV12_BUFFER_CONFIG *source, 329 YV12_BUFFER_CONFIG *post, 330 int q, 331 int low_var_thresh, 332 int flag) 333 { 334 double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065; 335 int ppl = (int)(level + .5); 336 337 const MODE_INFO *mode_info_context = cm->show_frame_mi; 338 int mbr, mbc; 339 340 /* The pixel thresholds are adjusted according to if or not the macroblock 341 * is a skipped block. */ 342 unsigned char *ylimits = cm->pp_limits_buffer; 343 unsigned char *uvlimits = cm->pp_limits_buffer + 16 * cm->mb_cols; 344 (void) low_var_thresh; 345 (void) flag; 346 347 if (ppl > 0) 348 { 349 for (mbr = 0; mbr < cm->mb_rows; mbr++) 350 { 351 unsigned char *ylptr = ylimits; 352 unsigned char *uvlptr = uvlimits; 353 for (mbc = 0; mbc < cm->mb_cols; mbc++) 354 { 355 unsigned char mb_ppl; 356 357 if (mode_info_context->mbmi.mb_skip_coeff) 358 mb_ppl = (unsigned char)ppl >> 1; 359 else 360 mb_ppl = (unsigned char)ppl; 361 362 vpx_memset(ylptr, mb_ppl, 16); 363 vpx_memset(uvlptr, mb_ppl, 8); 364 365 ylptr += 16; 366 uvlptr += 8; 367 mode_info_context++; 368 } 369 mode_info_context++; 370 371 vp8_post_proc_down_and_across_mb_row( 372 source->y_buffer + 16 * mbr * source->y_stride, 373 post->y_buffer + 16 * mbr * post->y_stride, source->y_stride, 374 post->y_stride, source->y_width, ylimits, 16); 375 376 vp8_post_proc_down_and_across_mb_row( 377 source->u_buffer + 8 * mbr * source->uv_stride, 378 post->u_buffer + 8 * mbr * post->uv_stride, source->uv_stride, 379 post->uv_stride, source->uv_width, uvlimits, 8); 380 vp8_post_proc_down_and_across_mb_row( 381 source->v_buffer + 8 * mbr * source->uv_stride, 382 post->v_buffer + 8 * mbr * post->uv_stride, source->uv_stride, 383 post->uv_stride, source->uv_width, uvlimits, 8); 384 } 385 } else 386 { 387 vp8_yv12_copy_frame(source, post); 388 } 389 } 390 391 #if !(CONFIG_TEMPORAL_DENOISING) 392 void vp8_de_noise(VP8_COMMON *cm, 393 YV12_BUFFER_CONFIG *source, 394 YV12_BUFFER_CONFIG *post, 395 int q, 396 int low_var_thresh, 397 int flag) 398 { 399 double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065; 400 int ppl = (int)(level + .5); 401 int mb_rows = source->y_width >> 4; 402 int mb_cols = source->y_height >> 4; 403 unsigned char *limits = cm->pp_limits_buffer;; 404 int mbr, mbc; 405 (void) post; 406 (void) low_var_thresh; 407 (void) flag; 408 409 vpx_memset(limits, (unsigned char)ppl, 16 * mb_cols); 410 411 /* TODO: The original code don't filter the 2 outer rows and columns. */ 412 for (mbr = 0; mbr < mb_rows; mbr++) 413 { 414 vp8_post_proc_down_and_across_mb_row( 415 source->y_buffer + 16 * mbr * source->y_stride, 416 source->y_buffer + 16 * mbr * source->y_stride, 417 source->y_stride, source->y_stride, source->y_width, limits, 16); 418 419 vp8_post_proc_down_and_across_mb_row( 420 source->u_buffer + 8 * mbr * source->uv_stride, 421 source->u_buffer + 8 * mbr * source->uv_stride, 422 source->uv_stride, source->uv_stride, source->uv_width, limits, 8); 423 vp8_post_proc_down_and_across_mb_row( 424 source->v_buffer + 8 * mbr * source->uv_stride, 425 source->v_buffer + 8 * mbr * source->uv_stride, 426 source->uv_stride, source->uv_stride, source->uv_width, limits, 8); 427 } 428 } 429 #endif 430 431 double vp8_gaussian(double sigma, double mu, double x) 432 { 433 return 1 / (sigma * sqrt(2.0 * 3.14159265)) * 434 (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma))); 435 } 436 437 static void fillrd(struct postproc_state *state, int q, int a) 438 { 439 char char_dist[300]; 440 441 double sigma; 442 int i; 443 444 vp8_clear_system_state(); 445 446 447 sigma = a + .5 + .6 * (63 - q) / 63.0; 448 449 /* set up a lookup table of 256 entries that matches 450 * a gaussian distribution with sigma determined by q. 451 */ 452 { 453 int next, j; 454 455 next = 0; 456 457 for (i = -32; i < 32; i++) 458 { 459 const int v = (int)(.5 + 256 * vp8_gaussian(sigma, 0, i)); 460 461 if (v) 462 { 463 for (j = 0; j < v; 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 y_1, int u_1, int v_1, int alpha, int stride) 547 { 548 int i, j; 549 int y1_const = y_1*((1<<16)-alpha); 550 int u1_const = u_1*((1<<16)-alpha); 551 int v1_const = v_1*((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 y_1, int u_1, int v_1, int alpha, int stride) 585 { 586 int i, j; 587 int y1_const = y_1*((1<<16)-alpha); 588 int u1_const = u_1*((1<<16)-alpha); 589 int v1_const = v_1*((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 y_1, int u_1, int v_1, int alpha, int stride) 649 { 650 int i, j; 651 int y1_const = y_1*((1<<16)-alpha); 652 int u1_const = u_1*((1<<16)-alpha); 653 int v1_const = v_1*((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 x_0, int *x_1, int y_0, int *y_1, int width, int height) 679 { 680 int dx; 681 int dy; 682 683 if (*x_1 > width) 684 { 685 dx = *x_1 - x_0; 686 dy = *y_1 - y_0; 687 688 *x_1 = width; 689 if (dx) 690 *y_1 = ((width-x_0)*dy)/dx + y_0; 691 } 692 if (*x_1 < 0) 693 { 694 dx = *x_1 - x_0; 695 dy = *y_1 - y_0; 696 697 *x_1 = 0; 698 if (dx) 699 *y_1 = ((0-x_0)*dy)/dx + y_0; 700 } 701 if (*y_1 > height) 702 { 703 dx = *x_1 - x_0; 704 dy = *y_1 - y_0; 705 706 *y_1 = height; 707 if (dy) 708 *x_1 = ((height-y_0)*dx)/dy + x_0; 709 } 710 if (*y_1 < 0) 711 { 712 dx = *x_1 - x_0; 713 dy = *y_1 - y_0; 714 715 *y_1 = 0; 716 if (dy) 717 *x_1 = ((0-y_0)*dx)/dy + x_0; 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 framerate: %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