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