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