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