1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libvpx/vp9/common/vp9_postproc.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1014 @@ 1.4 +/* 1.5 + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license 1.8 + * that can be found in the LICENSE file in the root of the source 1.9 + * tree. An additional intellectual property rights grant can be found 1.10 + * in the file PATENTS. All contributing project authors may 1.11 + * be found in the AUTHORS file in the root of the source tree. 1.12 + */ 1.13 + 1.14 +#include <math.h> 1.15 +#include <stdlib.h> 1.16 +#include <stdio.h> 1.17 + 1.18 +#include "./vpx_config.h" 1.19 +#include "vpx_scale/yv12config.h" 1.20 +#include "vp9/common/vp9_postproc.h" 1.21 +#include "vp9/common/vp9_textblit.h" 1.22 +#include "vpx_scale/vpx_scale.h" 1.23 +#include "vp9/common/vp9_systemdependent.h" 1.24 +#include "./vp9_rtcd.h" 1.25 +#include "./vpx_scale_rtcd.h" 1.26 + 1.27 +#define RGB_TO_YUV(t) \ 1.28 + ( (0.257*(float)(t >> 16)) + (0.504*(float)(t >> 8 & 0xff)) + \ 1.29 + (0.098*(float)(t & 0xff)) + 16), \ 1.30 + (-(0.148*(float)(t >> 16)) - (0.291*(float)(t >> 8 & 0xff)) + \ 1.31 + (0.439*(float)(t & 0xff)) + 128), \ 1.32 + ( (0.439*(float)(t >> 16)) - (0.368*(float)(t >> 8 & 0xff)) - \ 1.33 + (0.071*(float)(t & 0xff)) + 128) 1.34 + 1.35 +/* global constants */ 1.36 +#if 0 && CONFIG_POSTPROC_VISUALIZER 1.37 +static const unsigned char MB_PREDICTION_MODE_colors[MB_MODE_COUNT][3] = { 1.38 + { RGB_TO_YUV(0x98FB98) }, /* PaleGreen */ 1.39 + { RGB_TO_YUV(0x00FF00) }, /* Green */ 1.40 + { RGB_TO_YUV(0xADFF2F) }, /* GreenYellow */ 1.41 + { RGB_TO_YUV(0x8F0000) }, /* Dark Red */ 1.42 + { RGB_TO_YUV(0x008F8F) }, /* Dark Cyan */ 1.43 + { RGB_TO_YUV(0x008F8F) }, /* Dark Cyan */ 1.44 + { RGB_TO_YUV(0x008F8F) }, /* Dark Cyan */ 1.45 + { RGB_TO_YUV(0x8F0000) }, /* Dark Red */ 1.46 + { RGB_TO_YUV(0x8F0000) }, /* Dark Red */ 1.47 + { RGB_TO_YUV(0x228B22) }, /* ForestGreen */ 1.48 + { RGB_TO_YUV(0x006400) }, /* DarkGreen */ 1.49 + { RGB_TO_YUV(0x98F5FF) }, /* Cadet Blue */ 1.50 + { RGB_TO_YUV(0x6CA6CD) }, /* Sky Blue */ 1.51 + { RGB_TO_YUV(0x00008B) }, /* Dark blue */ 1.52 + { RGB_TO_YUV(0x551A8B) }, /* Purple */ 1.53 + { RGB_TO_YUV(0xFF0000) } /* Red */ 1.54 + { RGB_TO_YUV(0xCC33FF) }, /* Magenta */ 1.55 +}; 1.56 + 1.57 +static const unsigned char B_PREDICTION_MODE_colors[INTRA_MODES][3] = { 1.58 + { RGB_TO_YUV(0x6633ff) }, /* Purple */ 1.59 + { RGB_TO_YUV(0xcc33ff) }, /* Magenta */ 1.60 + { RGB_TO_YUV(0xff33cc) }, /* Pink */ 1.61 + { RGB_TO_YUV(0xff3366) }, /* Coral */ 1.62 + { RGB_TO_YUV(0x3366ff) }, /* Blue */ 1.63 + { RGB_TO_YUV(0xed00f5) }, /* Dark Blue */ 1.64 + { RGB_TO_YUV(0x2e00b8) }, /* Dark Purple */ 1.65 + { RGB_TO_YUV(0xff6633) }, /* Orange */ 1.66 + { RGB_TO_YUV(0x33ccff) }, /* Light Blue */ 1.67 + { RGB_TO_YUV(0x8ab800) }, /* Green */ 1.68 + { RGB_TO_YUV(0xffcc33) }, /* Light Orange */ 1.69 + { RGB_TO_YUV(0x33ffcc) }, /* Aqua */ 1.70 + { RGB_TO_YUV(0x66ff33) }, /* Light Green */ 1.71 + { RGB_TO_YUV(0xccff33) }, /* Yellow */ 1.72 +}; 1.73 + 1.74 +static const unsigned char MV_REFERENCE_FRAME_colors[MAX_REF_FRAMES][3] = { 1.75 + { RGB_TO_YUV(0x00ff00) }, /* Blue */ 1.76 + { RGB_TO_YUV(0x0000ff) }, /* Green */ 1.77 + { RGB_TO_YUV(0xffff00) }, /* Yellow */ 1.78 + { RGB_TO_YUV(0xff0000) }, /* Red */ 1.79 +}; 1.80 +#endif 1.81 + 1.82 +static const short kernel5[] = { 1.83 + 1, 1, 4, 1, 1 1.84 +}; 1.85 + 1.86 +const short vp9_rv[] = { 1.87 + 8, 5, 2, 2, 8, 12, 4, 9, 8, 3, 1.88 + 0, 3, 9, 0, 0, 0, 8, 3, 14, 4, 1.89 + 10, 1, 11, 14, 1, 14, 9, 6, 12, 11, 1.90 + 8, 6, 10, 0, 0, 8, 9, 0, 3, 14, 1.91 + 8, 11, 13, 4, 2, 9, 0, 3, 9, 6, 1.92 + 1, 2, 3, 14, 13, 1, 8, 2, 9, 7, 1.93 + 3, 3, 1, 13, 13, 6, 6, 5, 2, 7, 1.94 + 11, 9, 11, 8, 7, 3, 2, 0, 13, 13, 1.95 + 14, 4, 12, 5, 12, 10, 8, 10, 13, 10, 1.96 + 4, 14, 4, 10, 0, 8, 11, 1, 13, 7, 1.97 + 7, 14, 6, 14, 13, 2, 13, 5, 4, 4, 1.98 + 0, 10, 0, 5, 13, 2, 12, 7, 11, 13, 1.99 + 8, 0, 4, 10, 7, 2, 7, 2, 2, 5, 1.100 + 3, 4, 7, 3, 3, 14, 14, 5, 9, 13, 1.101 + 3, 14, 3, 6, 3, 0, 11, 8, 13, 1, 1.102 + 13, 1, 12, 0, 10, 9, 7, 6, 2, 8, 1.103 + 5, 2, 13, 7, 1, 13, 14, 7, 6, 7, 1.104 + 9, 6, 10, 11, 7, 8, 7, 5, 14, 8, 1.105 + 4, 4, 0, 8, 7, 10, 0, 8, 14, 11, 1.106 + 3, 12, 5, 7, 14, 3, 14, 5, 2, 6, 1.107 + 11, 12, 12, 8, 0, 11, 13, 1, 2, 0, 1.108 + 5, 10, 14, 7, 8, 0, 4, 11, 0, 8, 1.109 + 0, 3, 10, 5, 8, 0, 11, 6, 7, 8, 1.110 + 10, 7, 13, 9, 2, 5, 1, 5, 10, 2, 1.111 + 4, 3, 5, 6, 10, 8, 9, 4, 11, 14, 1.112 + 0, 10, 0, 5, 13, 2, 12, 7, 11, 13, 1.113 + 8, 0, 4, 10, 7, 2, 7, 2, 2, 5, 1.114 + 3, 4, 7, 3, 3, 14, 14, 5, 9, 13, 1.115 + 3, 14, 3, 6, 3, 0, 11, 8, 13, 1, 1.116 + 13, 1, 12, 0, 10, 9, 7, 6, 2, 8, 1.117 + 5, 2, 13, 7, 1, 13, 14, 7, 6, 7, 1.118 + 9, 6, 10, 11, 7, 8, 7, 5, 14, 8, 1.119 + 4, 4, 0, 8, 7, 10, 0, 8, 14, 11, 1.120 + 3, 12, 5, 7, 14, 3, 14, 5, 2, 6, 1.121 + 11, 12, 12, 8, 0, 11, 13, 1, 2, 0, 1.122 + 5, 10, 14, 7, 8, 0, 4, 11, 0, 8, 1.123 + 0, 3, 10, 5, 8, 0, 11, 6, 7, 8, 1.124 + 10, 7, 13, 9, 2, 5, 1, 5, 10, 2, 1.125 + 4, 3, 5, 6, 10, 8, 9, 4, 11, 14, 1.126 + 3, 8, 3, 7, 8, 5, 11, 4, 12, 3, 1.127 + 11, 9, 14, 8, 14, 13, 4, 3, 1, 2, 1.128 + 14, 6, 5, 4, 4, 11, 4, 6, 2, 1, 1.129 + 5, 8, 8, 12, 13, 5, 14, 10, 12, 13, 1.130 + 0, 9, 5, 5, 11, 10, 13, 9, 10, 13, 1.131 +}; 1.132 + 1.133 + 1.134 +/**************************************************************************** 1.135 + */ 1.136 +void vp9_post_proc_down_and_across_c(const uint8_t *src_ptr, 1.137 + uint8_t *dst_ptr, 1.138 + int src_pixels_per_line, 1.139 + int dst_pixels_per_line, 1.140 + int rows, 1.141 + int cols, 1.142 + int flimit) { 1.143 + uint8_t const *p_src; 1.144 + uint8_t *p_dst; 1.145 + int row; 1.146 + int col; 1.147 + int i; 1.148 + int v; 1.149 + int pitch = src_pixels_per_line; 1.150 + uint8_t d[8]; 1.151 + (void)dst_pixels_per_line; 1.152 + 1.153 + for (row = 0; row < rows; row++) { 1.154 + /* post_proc_down for one row */ 1.155 + p_src = src_ptr; 1.156 + p_dst = dst_ptr; 1.157 + 1.158 + for (col = 0; col < cols; col++) { 1.159 + int kernel = 4; 1.160 + int v = p_src[col]; 1.161 + 1.162 + for (i = -2; i <= 2; i++) { 1.163 + if (abs(v - p_src[col + i * pitch]) > flimit) 1.164 + goto down_skip_convolve; 1.165 + 1.166 + kernel += kernel5[2 + i] * p_src[col + i * pitch]; 1.167 + } 1.168 + 1.169 + v = (kernel >> 3); 1.170 + down_skip_convolve: 1.171 + p_dst[col] = v; 1.172 + } 1.173 + 1.174 + /* now post_proc_across */ 1.175 + p_src = dst_ptr; 1.176 + p_dst = dst_ptr; 1.177 + 1.178 + for (i = 0; i < 8; i++) 1.179 + d[i] = p_src[i]; 1.180 + 1.181 + for (col = 0; col < cols; col++) { 1.182 + int kernel = 4; 1.183 + v = p_src[col]; 1.184 + 1.185 + d[col & 7] = v; 1.186 + 1.187 + for (i = -2; i <= 2; i++) { 1.188 + if (abs(v - p_src[col + i]) > flimit) 1.189 + goto across_skip_convolve; 1.190 + 1.191 + kernel += kernel5[2 + i] * p_src[col + i]; 1.192 + } 1.193 + 1.194 + d[col & 7] = (kernel >> 3); 1.195 + across_skip_convolve: 1.196 + 1.197 + if (col >= 2) 1.198 + p_dst[col - 2] = d[(col - 2) & 7]; 1.199 + } 1.200 + 1.201 + /* handle the last two pixels */ 1.202 + p_dst[col - 2] = d[(col - 2) & 7]; 1.203 + p_dst[col - 1] = d[(col - 1) & 7]; 1.204 + 1.205 + 1.206 + /* next row */ 1.207 + src_ptr += pitch; 1.208 + dst_ptr += pitch; 1.209 + } 1.210 +} 1.211 + 1.212 +static int q2mbl(int x) { 1.213 + if (x < 20) x = 20; 1.214 + 1.215 + x = 50 + (x - 50) * 10 / 8; 1.216 + return x * x / 3; 1.217 +} 1.218 + 1.219 +void vp9_mbpost_proc_across_ip_c(uint8_t *src, int pitch, 1.220 + int rows, int cols, int flimit) { 1.221 + int r, c, i; 1.222 + 1.223 + uint8_t *s = src; 1.224 + uint8_t d[16]; 1.225 + 1.226 + 1.227 + for (r = 0; r < rows; r++) { 1.228 + int sumsq = 0; 1.229 + int sum = 0; 1.230 + 1.231 + for (i = -8; i <= 6; i++) { 1.232 + sumsq += s[i] * s[i]; 1.233 + sum += s[i]; 1.234 + d[i + 8] = 0; 1.235 + } 1.236 + 1.237 + for (c = 0; c < cols + 8; c++) { 1.238 + int x = s[c + 7] - s[c - 8]; 1.239 + int y = s[c + 7] + s[c - 8]; 1.240 + 1.241 + sum += x; 1.242 + sumsq += x * y; 1.243 + 1.244 + d[c & 15] = s[c]; 1.245 + 1.246 + if (sumsq * 15 - sum * sum < flimit) { 1.247 + d[c & 15] = (8 + sum + s[c]) >> 4; 1.248 + } 1.249 + 1.250 + s[c - 8] = d[(c - 8) & 15]; 1.251 + } 1.252 + 1.253 + s += pitch; 1.254 + } 1.255 +} 1.256 + 1.257 +void vp9_mbpost_proc_down_c(uint8_t *dst, int pitch, 1.258 + int rows, int cols, int flimit) { 1.259 + int r, c, i; 1.260 + const short *rv3 = &vp9_rv[63 & rand()]; // NOLINT 1.261 + 1.262 + for (c = 0; c < cols; c++) { 1.263 + uint8_t *s = &dst[c]; 1.264 + int sumsq = 0; 1.265 + int sum = 0; 1.266 + uint8_t d[16]; 1.267 + const short *rv2 = rv3 + ((c * 17) & 127); 1.268 + 1.269 + for (i = -8; i <= 6; i++) { 1.270 + sumsq += s[i * pitch] * s[i * pitch]; 1.271 + sum += s[i * pitch]; 1.272 + } 1.273 + 1.274 + for (r = 0; r < rows + 8; r++) { 1.275 + sumsq += s[7 * pitch] * s[ 7 * pitch] - s[-8 * pitch] * s[-8 * pitch]; 1.276 + sum += s[7 * pitch] - s[-8 * pitch]; 1.277 + d[r & 15] = s[0]; 1.278 + 1.279 + if (sumsq * 15 - sum * sum < flimit) { 1.280 + d[r & 15] = (rv2[r & 127] + sum + s[0]) >> 4; 1.281 + } 1.282 + 1.283 + s[-8 * pitch] = d[(r - 8) & 15]; 1.284 + s += pitch; 1.285 + } 1.286 + } 1.287 +} 1.288 + 1.289 +static void deblock_and_de_macro_block(YV12_BUFFER_CONFIG *source, 1.290 + YV12_BUFFER_CONFIG *post, 1.291 + int q, 1.292 + int low_var_thresh, 1.293 + int flag) { 1.294 + double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065; 1.295 + int ppl = (int)(level + .5); 1.296 + (void) low_var_thresh; 1.297 + (void) flag; 1.298 + 1.299 + vp9_post_proc_down_and_across(source->y_buffer, post->y_buffer, 1.300 + source->y_stride, post->y_stride, 1.301 + source->y_height, source->y_width, ppl); 1.302 + 1.303 + vp9_mbpost_proc_across_ip(post->y_buffer, post->y_stride, post->y_height, 1.304 + post->y_width, q2mbl(q)); 1.305 + 1.306 + vp9_mbpost_proc_down(post->y_buffer, post->y_stride, post->y_height, 1.307 + post->y_width, q2mbl(q)); 1.308 + 1.309 + vp9_post_proc_down_and_across(source->u_buffer, post->u_buffer, 1.310 + source->uv_stride, post->uv_stride, 1.311 + source->uv_height, source->uv_width, ppl); 1.312 + vp9_post_proc_down_and_across(source->v_buffer, post->v_buffer, 1.313 + source->uv_stride, post->uv_stride, 1.314 + source->uv_height, source->uv_width, ppl); 1.315 +} 1.316 + 1.317 +void vp9_deblock(const YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst, 1.318 + int q) { 1.319 + const int ppl = (int)(6.0e-05 * q * q * q - 0.0067 * q * q + 0.306 * q 1.320 + + 0.0065 + 0.5); 1.321 + int i; 1.322 + 1.323 + const uint8_t *const srcs[4] = {src->y_buffer, src->u_buffer, src->v_buffer, 1.324 + src->alpha_buffer}; 1.325 + const int src_strides[4] = {src->y_stride, src->uv_stride, src->uv_stride, 1.326 + src->alpha_stride}; 1.327 + const int src_widths[4] = {src->y_width, src->uv_width, src->uv_width, 1.328 + src->alpha_width}; 1.329 + const int src_heights[4] = {src->y_height, src->uv_height, src->uv_height, 1.330 + src->alpha_height}; 1.331 + 1.332 + uint8_t *const dsts[4] = {dst->y_buffer, dst->u_buffer, dst->v_buffer, 1.333 + dst->alpha_buffer}; 1.334 + const int dst_strides[4] = {dst->y_stride, dst->uv_stride, dst->uv_stride, 1.335 + dst->alpha_stride}; 1.336 + 1.337 + for (i = 0; i < MAX_MB_PLANE; ++i) 1.338 + vp9_post_proc_down_and_across(srcs[i], dsts[i], 1.339 + src_strides[i], dst_strides[i], 1.340 + src_heights[i], src_widths[i], ppl); 1.341 +} 1.342 + 1.343 +void vp9_denoise(const YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst, 1.344 + int q) { 1.345 + const int ppl = (int)(6.0e-05 * q * q * q - 0.0067 * q * q + 0.306 * q 1.346 + + 0.0065 + 0.5); 1.347 + int i; 1.348 + 1.349 + const uint8_t *const srcs[4] = {src->y_buffer, src->u_buffer, src->v_buffer, 1.350 + src->alpha_buffer}; 1.351 + const int src_strides[4] = {src->y_stride, src->uv_stride, src->uv_stride, 1.352 + src->alpha_stride}; 1.353 + const int src_widths[4] = {src->y_width, src->uv_width, src->uv_width, 1.354 + src->alpha_width}; 1.355 + const int src_heights[4] = {src->y_height, src->uv_height, src->uv_height, 1.356 + src->alpha_height}; 1.357 + 1.358 + uint8_t *const dsts[4] = {dst->y_buffer, dst->u_buffer, dst->v_buffer, 1.359 + dst->alpha_buffer}; 1.360 + const int dst_strides[4] = {dst->y_stride, dst->uv_stride, dst->uv_stride, 1.361 + dst->alpha_stride}; 1.362 + 1.363 + for (i = 0; i < MAX_MB_PLANE; ++i) { 1.364 + const int src_stride = src_strides[i]; 1.365 + const uint8_t *const src = srcs[i] + 2 * src_stride + 2; 1.366 + const int src_width = src_widths[i] - 4; 1.367 + const int src_height = src_heights[i] - 4; 1.368 + 1.369 + const int dst_stride = dst_strides[i]; 1.370 + uint8_t *const dst = dsts[i] + 2 * dst_stride + 2; 1.371 + 1.372 + vp9_post_proc_down_and_across(src, dst, src_stride, dst_stride, 1.373 + src_height, src_width, ppl); 1.374 + } 1.375 +} 1.376 + 1.377 +double vp9_gaussian(double sigma, double mu, double x) { 1.378 + return 1 / (sigma * sqrt(2.0 * 3.14159265)) * 1.379 + (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma))); 1.380 +} 1.381 + 1.382 +static void fillrd(struct postproc_state *state, int q, int a) { 1.383 + char char_dist[300]; 1.384 + 1.385 + double sigma; 1.386 + int ai = a, qi = q, i; 1.387 + 1.388 + vp9_clear_system_state(); 1.389 + 1.390 + sigma = ai + .5 + .6 * (63 - qi) / 63.0; 1.391 + 1.392 + /* set up a lookup table of 256 entries that matches 1.393 + * a gaussian distribution with sigma determined by q. 1.394 + */ 1.395 + { 1.396 + double i; 1.397 + int next, j; 1.398 + 1.399 + next = 0; 1.400 + 1.401 + for (i = -32; i < 32; i++) { 1.402 + int a = (int)(.5 + 256 * vp9_gaussian(sigma, 0, i)); 1.403 + 1.404 + if (a) { 1.405 + for (j = 0; j < a; j++) { 1.406 + char_dist[next + j] = (char) i; 1.407 + } 1.408 + 1.409 + next = next + j; 1.410 + } 1.411 + } 1.412 + 1.413 + for (; next < 256; next++) 1.414 + char_dist[next] = 0; 1.415 + } 1.416 + 1.417 + for (i = 0; i < 3072; i++) { 1.418 + state->noise[i] = char_dist[rand() & 0xff]; // NOLINT 1.419 + } 1.420 + 1.421 + for (i = 0; i < 16; i++) { 1.422 + state->blackclamp[i] = -char_dist[0]; 1.423 + state->whiteclamp[i] = -char_dist[0]; 1.424 + state->bothclamp[i] = -2 * char_dist[0]; 1.425 + } 1.426 + 1.427 + state->last_q = q; 1.428 + state->last_noise = a; 1.429 +} 1.430 + 1.431 +/**************************************************************************** 1.432 + * 1.433 + * ROUTINE : plane_add_noise_c 1.434 + * 1.435 + * INPUTS : unsigned char *Start starting address of buffer to 1.436 + * add gaussian noise to 1.437 + * unsigned int width width of plane 1.438 + * unsigned int height height of plane 1.439 + * int pitch distance between subsequent lines of frame 1.440 + * int q quantizer used to determine amount of noise 1.441 + * to add 1.442 + * 1.443 + * OUTPUTS : None. 1.444 + * 1.445 + * RETURNS : void. 1.446 + * 1.447 + * FUNCTION : adds gaussian noise to a plane of pixels 1.448 + * 1.449 + * SPECIAL NOTES : None. 1.450 + * 1.451 + ****************************************************************************/ 1.452 +void vp9_plane_add_noise_c(uint8_t *start, char *noise, 1.453 + char blackclamp[16], 1.454 + char whiteclamp[16], 1.455 + char bothclamp[16], 1.456 + unsigned int width, unsigned int height, int pitch) { 1.457 + unsigned int i, j; 1.458 + 1.459 + for (i = 0; i < height; i++) { 1.460 + uint8_t *pos = start + i * pitch; 1.461 + char *ref = (char *)(noise + (rand() & 0xff)); // NOLINT 1.462 + 1.463 + for (j = 0; j < width; j++) { 1.464 + if (pos[j] < blackclamp[0]) 1.465 + pos[j] = blackclamp[0]; 1.466 + 1.467 + if (pos[j] > 255 + whiteclamp[0]) 1.468 + pos[j] = 255 + whiteclamp[0]; 1.469 + 1.470 + pos[j] += ref[j]; 1.471 + } 1.472 + } 1.473 +} 1.474 + 1.475 +/* Blend the macro block with a solid colored square. Leave the 1.476 + * edges unblended to give distinction to macro blocks in areas 1.477 + * filled with the same color block. 1.478 + */ 1.479 +void vp9_blend_mb_inner_c(uint8_t *y, uint8_t *u, uint8_t *v, 1.480 + int y1, int u1, int v1, int alpha, int stride) { 1.481 + int i, j; 1.482 + int y1_const = y1 * ((1 << 16) - alpha); 1.483 + int u1_const = u1 * ((1 << 16) - alpha); 1.484 + int v1_const = v1 * ((1 << 16) - alpha); 1.485 + 1.486 + y += 2 * stride + 2; 1.487 + for (i = 0; i < 12; i++) { 1.488 + for (j = 0; j < 12; j++) { 1.489 + y[j] = (y[j] * alpha + y1_const) >> 16; 1.490 + } 1.491 + y += stride; 1.492 + } 1.493 + 1.494 + stride >>= 1; 1.495 + 1.496 + u += stride + 1; 1.497 + v += stride + 1; 1.498 + 1.499 + for (i = 0; i < 6; i++) { 1.500 + for (j = 0; j < 6; j++) { 1.501 + u[j] = (u[j] * alpha + u1_const) >> 16; 1.502 + v[j] = (v[j] * alpha + v1_const) >> 16; 1.503 + } 1.504 + u += stride; 1.505 + v += stride; 1.506 + } 1.507 +} 1.508 + 1.509 +/* Blend only the edge of the macro block. Leave center 1.510 + * unblended to allow for other visualizations to be layered. 1.511 + */ 1.512 +void vp9_blend_mb_outer_c(uint8_t *y, uint8_t *u, uint8_t *v, 1.513 + int y1, int u1, int v1, int alpha, int stride) { 1.514 + int i, j; 1.515 + int y1_const = y1 * ((1 << 16) - alpha); 1.516 + int u1_const = u1 * ((1 << 16) - alpha); 1.517 + int v1_const = v1 * ((1 << 16) - alpha); 1.518 + 1.519 + for (i = 0; i < 2; i++) { 1.520 + for (j = 0; j < 16; j++) { 1.521 + y[j] = (y[j] * alpha + y1_const) >> 16; 1.522 + } 1.523 + y += stride; 1.524 + } 1.525 + 1.526 + for (i = 0; i < 12; i++) { 1.527 + y[0] = (y[0] * alpha + y1_const) >> 16; 1.528 + y[1] = (y[1] * alpha + y1_const) >> 16; 1.529 + y[14] = (y[14] * alpha + y1_const) >> 16; 1.530 + y[15] = (y[15] * alpha + y1_const) >> 16; 1.531 + y += stride; 1.532 + } 1.533 + 1.534 + for (i = 0; i < 2; i++) { 1.535 + for (j = 0; j < 16; j++) { 1.536 + y[j] = (y[j] * alpha + y1_const) >> 16; 1.537 + } 1.538 + y += stride; 1.539 + } 1.540 + 1.541 + stride >>= 1; 1.542 + 1.543 + for (j = 0; j < 8; j++) { 1.544 + u[j] = (u[j] * alpha + u1_const) >> 16; 1.545 + v[j] = (v[j] * alpha + v1_const) >> 16; 1.546 + } 1.547 + u += stride; 1.548 + v += stride; 1.549 + 1.550 + for (i = 0; i < 6; i++) { 1.551 + u[0] = (u[0] * alpha + u1_const) >> 16; 1.552 + v[0] = (v[0] * alpha + v1_const) >> 16; 1.553 + 1.554 + u[7] = (u[7] * alpha + u1_const) >> 16; 1.555 + v[7] = (v[7] * alpha + v1_const) >> 16; 1.556 + 1.557 + u += stride; 1.558 + v += stride; 1.559 + } 1.560 + 1.561 + for (j = 0; j < 8; j++) { 1.562 + u[j] = (u[j] * alpha + u1_const) >> 16; 1.563 + v[j] = (v[j] * alpha + v1_const) >> 16; 1.564 + } 1.565 +} 1.566 + 1.567 +void vp9_blend_b_c(uint8_t *y, uint8_t *u, uint8_t *v, 1.568 + int y1, int u1, int v1, int alpha, int stride) { 1.569 + int i, j; 1.570 + int y1_const = y1 * ((1 << 16) - alpha); 1.571 + int u1_const = u1 * ((1 << 16) - alpha); 1.572 + int v1_const = v1 * ((1 << 16) - alpha); 1.573 + 1.574 + for (i = 0; i < 4; i++) { 1.575 + for (j = 0; j < 4; j++) { 1.576 + y[j] = (y[j] * alpha + y1_const) >> 16; 1.577 + } 1.578 + y += stride; 1.579 + } 1.580 + 1.581 + stride >>= 1; 1.582 + 1.583 + for (i = 0; i < 2; i++) { 1.584 + for (j = 0; j < 2; j++) { 1.585 + u[j] = (u[j] * alpha + u1_const) >> 16; 1.586 + v[j] = (v[j] * alpha + v1_const) >> 16; 1.587 + } 1.588 + u += stride; 1.589 + v += stride; 1.590 + } 1.591 +} 1.592 + 1.593 +static void constrain_line(int x0, int *x1, int y0, int *y1, 1.594 + int width, int height) { 1.595 + int dx; 1.596 + int dy; 1.597 + 1.598 + if (*x1 > width) { 1.599 + dx = *x1 - x0; 1.600 + dy = *y1 - y0; 1.601 + 1.602 + *x1 = width; 1.603 + if (dx) 1.604 + *y1 = ((width - x0) * dy) / dx + y0; 1.605 + } 1.606 + if (*x1 < 0) { 1.607 + dx = *x1 - x0; 1.608 + dy = *y1 - y0; 1.609 + 1.610 + *x1 = 0; 1.611 + if (dx) 1.612 + *y1 = ((0 - x0) * dy) / dx + y0; 1.613 + } 1.614 + if (*y1 > height) { 1.615 + dx = *x1 - x0; 1.616 + dy = *y1 - y0; 1.617 + 1.618 + *y1 = height; 1.619 + if (dy) 1.620 + *x1 = ((height - y0) * dx) / dy + x0; 1.621 + } 1.622 + if (*y1 < 0) { 1.623 + dx = *x1 - x0; 1.624 + dy = *y1 - y0; 1.625 + 1.626 + *y1 = 0; 1.627 + if (dy) 1.628 + *x1 = ((0 - y0) * dx) / dy + x0; 1.629 + } 1.630 +} 1.631 + 1.632 +int vp9_post_proc_frame(struct VP9Common *cm, 1.633 + YV12_BUFFER_CONFIG *dest, vp9_ppflags_t *ppflags) { 1.634 + int q = cm->lf.filter_level * 10 / 6; 1.635 + int flags = ppflags->post_proc_flag; 1.636 + int deblock_level = ppflags->deblocking_level; 1.637 + int noise_level = ppflags->noise_level; 1.638 + 1.639 + if (!cm->frame_to_show) 1.640 + return -1; 1.641 + 1.642 + if (q > 63) 1.643 + q = 63; 1.644 + 1.645 + if (!flags) { 1.646 + *dest = *cm->frame_to_show; 1.647 + return 0; 1.648 + } 1.649 + 1.650 +#if ARCH_X86||ARCH_X86_64 1.651 + vpx_reset_mmx_state(); 1.652 +#endif 1.653 + 1.654 + if (flags & VP9D_DEMACROBLOCK) { 1.655 + deblock_and_de_macro_block(cm->frame_to_show, &cm->post_proc_buffer, 1.656 + q + (deblock_level - 5) * 10, 1, 0); 1.657 + } else if (flags & VP9D_DEBLOCK) { 1.658 + vp9_deblock(cm->frame_to_show, &cm->post_proc_buffer, q); 1.659 + } else { 1.660 + vp8_yv12_copy_frame(cm->frame_to_show, &cm->post_proc_buffer); 1.661 + } 1.662 + 1.663 + if (flags & VP9D_ADDNOISE) { 1.664 + if (cm->postproc_state.last_q != q 1.665 + || cm->postproc_state.last_noise != noise_level) { 1.666 + fillrd(&cm->postproc_state, 63 - q, noise_level); 1.667 + } 1.668 + 1.669 + vp9_plane_add_noise(cm->post_proc_buffer.y_buffer, 1.670 + cm->postproc_state.noise, 1.671 + cm->postproc_state.blackclamp, 1.672 + cm->postproc_state.whiteclamp, 1.673 + cm->postproc_state.bothclamp, 1.674 + cm->post_proc_buffer.y_width, 1.675 + cm->post_proc_buffer.y_height, 1.676 + cm->post_proc_buffer.y_stride); 1.677 + } 1.678 + 1.679 +#if 0 && CONFIG_POSTPROC_VISUALIZER 1.680 + if (flags & VP9D_DEBUG_TXT_FRAME_INFO) { 1.681 + char message[512]; 1.682 + snprintf(message, sizeof(message) -1, 1.683 + "F%1dG%1dQ%3dF%3dP%d_s%dx%d", 1.684 + (cm->frame_type == KEY_FRAME), 1.685 + cm->refresh_golden_frame, 1.686 + cm->base_qindex, 1.687 + cm->filter_level, 1.688 + flags, 1.689 + cm->mb_cols, cm->mb_rows); 1.690 + vp9_blit_text(message, cm->post_proc_buffer.y_buffer, 1.691 + cm->post_proc_buffer.y_stride); 1.692 + } 1.693 + 1.694 + if (flags & VP9D_DEBUG_TXT_MBLK_MODES) { 1.695 + int i, j; 1.696 + uint8_t *y_ptr; 1.697 + YV12_BUFFER_CONFIG *post = &cm->post_proc_buffer; 1.698 + int mb_rows = post->y_height >> 4; 1.699 + int mb_cols = post->y_width >> 4; 1.700 + int mb_index = 0; 1.701 + MODE_INFO *mi = cm->mi; 1.702 + 1.703 + y_ptr = post->y_buffer + 4 * post->y_stride + 4; 1.704 + 1.705 + /* vp9_filter each macro block */ 1.706 + for (i = 0; i < mb_rows; i++) { 1.707 + for (j = 0; j < mb_cols; j++) { 1.708 + char zz[4]; 1.709 + 1.710 + snprintf(zz, sizeof(zz) - 1, "%c", mi[mb_index].mbmi.mode + 'a'); 1.711 + 1.712 + vp9_blit_text(zz, y_ptr, post->y_stride); 1.713 + mb_index++; 1.714 + y_ptr += 16; 1.715 + } 1.716 + 1.717 + mb_index++; /* border */ 1.718 + y_ptr += post->y_stride * 16 - post->y_width; 1.719 + } 1.720 + } 1.721 + 1.722 + if (flags & VP9D_DEBUG_TXT_DC_DIFF) { 1.723 + int i, j; 1.724 + uint8_t *y_ptr; 1.725 + YV12_BUFFER_CONFIG *post = &cm->post_proc_buffer; 1.726 + int mb_rows = post->y_height >> 4; 1.727 + int mb_cols = post->y_width >> 4; 1.728 + int mb_index = 0; 1.729 + MODE_INFO *mi = cm->mi; 1.730 + 1.731 + y_ptr = post->y_buffer + 4 * post->y_stride + 4; 1.732 + 1.733 + /* vp9_filter each macro block */ 1.734 + for (i = 0; i < mb_rows; i++) { 1.735 + for (j = 0; j < mb_cols; j++) { 1.736 + char zz[4]; 1.737 + int dc_diff = !(mi[mb_index].mbmi.mode != I4X4_PRED && 1.738 + mi[mb_index].mbmi.mode != SPLITMV && 1.739 + mi[mb_index].mbmi.skip_coeff); 1.740 + 1.741 + if (cm->frame_type == KEY_FRAME) 1.742 + snprintf(zz, sizeof(zz) - 1, "a"); 1.743 + else 1.744 + snprintf(zz, sizeof(zz) - 1, "%c", dc_diff + '0'); 1.745 + 1.746 + vp9_blit_text(zz, y_ptr, post->y_stride); 1.747 + mb_index++; 1.748 + y_ptr += 16; 1.749 + } 1.750 + 1.751 + mb_index++; /* border */ 1.752 + y_ptr += post->y_stride * 16 - post->y_width; 1.753 + } 1.754 + } 1.755 + 1.756 + if (flags & VP9D_DEBUG_TXT_RATE_INFO) { 1.757 + char message[512]; 1.758 + snprintf(message, sizeof(message), 1.759 + "Bitrate: %10.2f framerate: %10.2f ", 1.760 + cm->bitrate, cm->framerate); 1.761 + vp9_blit_text(message, cm->post_proc_buffer.y_buffer, 1.762 + cm->post_proc_buffer.y_stride); 1.763 + } 1.764 + 1.765 + /* Draw motion vectors */ 1.766 + if ((flags & VP9D_DEBUG_DRAW_MV) && ppflags->display_mv_flag) { 1.767 + YV12_BUFFER_CONFIG *post = &cm->post_proc_buffer; 1.768 + int width = post->y_width; 1.769 + int height = post->y_height; 1.770 + uint8_t *y_buffer = cm->post_proc_buffer.y_buffer; 1.771 + int y_stride = cm->post_proc_buffer.y_stride; 1.772 + MODE_INFO *mi = cm->mi; 1.773 + int x0, y0; 1.774 + 1.775 + for (y0 = 0; y0 < height; y0 += 16) { 1.776 + for (x0 = 0; x0 < width; x0 += 16) { 1.777 + int x1, y1; 1.778 + 1.779 + if (!(ppflags->display_mv_flag & (1 << mi->mbmi.mode))) { 1.780 + mi++; 1.781 + continue; 1.782 + } 1.783 + 1.784 + if (mi->mbmi.mode == SPLITMV) { 1.785 + switch (mi->mbmi.partitioning) { 1.786 + case PARTITIONING_16X8 : { /* mv_top_bottom */ 1.787 + union b_mode_info *bmi = &mi->bmi[0]; 1.788 + MV *mv = &bmi->mv.as_mv; 1.789 + 1.790 + x1 = x0 + 8 + (mv->col >> 3); 1.791 + y1 = y0 + 4 + (mv->row >> 3); 1.792 + 1.793 + constrain_line(x0 + 8, &x1, y0 + 4, &y1, width, height); 1.794 + vp9_blit_line(x0 + 8, x1, y0 + 4, y1, y_buffer, y_stride); 1.795 + 1.796 + bmi = &mi->bmi[8]; 1.797 + 1.798 + x1 = x0 + 8 + (mv->col >> 3); 1.799 + y1 = y0 + 12 + (mv->row >> 3); 1.800 + 1.801 + constrain_line(x0 + 8, &x1, y0 + 12, &y1, width, height); 1.802 + vp9_blit_line(x0 + 8, x1, y0 + 12, y1, y_buffer, y_stride); 1.803 + 1.804 + break; 1.805 + } 1.806 + case PARTITIONING_8X16 : { /* mv_left_right */ 1.807 + union b_mode_info *bmi = &mi->bmi[0]; 1.808 + MV *mv = &bmi->mv.as_mv; 1.809 + 1.810 + x1 = x0 + 4 + (mv->col >> 3); 1.811 + y1 = y0 + 8 + (mv->row >> 3); 1.812 + 1.813 + constrain_line(x0 + 4, &x1, y0 + 8, &y1, width, height); 1.814 + vp9_blit_line(x0 + 4, x1, y0 + 8, y1, y_buffer, y_stride); 1.815 + 1.816 + bmi = &mi->bmi[2]; 1.817 + 1.818 + x1 = x0 + 12 + (mv->col >> 3); 1.819 + y1 = y0 + 8 + (mv->row >> 3); 1.820 + 1.821 + constrain_line(x0 + 12, &x1, y0 + 8, &y1, width, height); 1.822 + vp9_blit_line(x0 + 12, x1, y0 + 8, y1, y_buffer, y_stride); 1.823 + 1.824 + break; 1.825 + } 1.826 + case PARTITIONING_8X8 : { /* mv_quarters */ 1.827 + union b_mode_info *bmi = &mi->bmi[0]; 1.828 + MV *mv = &bmi->mv.as_mv; 1.829 + 1.830 + x1 = x0 + 4 + (mv->col >> 3); 1.831 + y1 = y0 + 4 + (mv->row >> 3); 1.832 + 1.833 + constrain_line(x0 + 4, &x1, y0 + 4, &y1, width, height); 1.834 + vp9_blit_line(x0 + 4, x1, y0 + 4, y1, y_buffer, y_stride); 1.835 + 1.836 + bmi = &mi->bmi[2]; 1.837 + 1.838 + x1 = x0 + 12 + (mv->col >> 3); 1.839 + y1 = y0 + 4 + (mv->row >> 3); 1.840 + 1.841 + constrain_line(x0 + 12, &x1, y0 + 4, &y1, width, height); 1.842 + vp9_blit_line(x0 + 12, x1, y0 + 4, y1, y_buffer, y_stride); 1.843 + 1.844 + bmi = &mi->bmi[8]; 1.845 + 1.846 + x1 = x0 + 4 + (mv->col >> 3); 1.847 + y1 = y0 + 12 + (mv->row >> 3); 1.848 + 1.849 + constrain_line(x0 + 4, &x1, y0 + 12, &y1, width, height); 1.850 + vp9_blit_line(x0 + 4, x1, y0 + 12, y1, y_buffer, y_stride); 1.851 + 1.852 + bmi = &mi->bmi[10]; 1.853 + 1.854 + x1 = x0 + 12 + (mv->col >> 3); 1.855 + y1 = y0 + 12 + (mv->row >> 3); 1.856 + 1.857 + constrain_line(x0 + 12, &x1, y0 + 12, &y1, width, height); 1.858 + vp9_blit_line(x0 + 12, x1, y0 + 12, y1, y_buffer, y_stride); 1.859 + break; 1.860 + } 1.861 + case PARTITIONING_4X4: 1.862 + default : { 1.863 + union b_mode_info *bmi = mi->bmi; 1.864 + int bx0, by0; 1.865 + 1.866 + for (by0 = y0; by0 < (y0 + 16); by0 += 4) { 1.867 + for (bx0 = x0; bx0 < (x0 + 16); bx0 += 4) { 1.868 + MV *mv = &bmi->mv.as_mv; 1.869 + 1.870 + x1 = bx0 + 2 + (mv->col >> 3); 1.871 + y1 = by0 + 2 + (mv->row >> 3); 1.872 + 1.873 + constrain_line(bx0 + 2, &x1, by0 + 2, &y1, width, height); 1.874 + vp9_blit_line(bx0 + 2, x1, by0 + 2, y1, y_buffer, y_stride); 1.875 + 1.876 + bmi++; 1.877 + } 1.878 + } 1.879 + } 1.880 + } 1.881 + } else if (is_inter_mode(mi->mbmi.mode)) { 1.882 + MV *mv = &mi->mbmi.mv.as_mv; 1.883 + const int lx0 = x0 + 8; 1.884 + const int ly0 = y0 + 8; 1.885 + 1.886 + x1 = lx0 + (mv->col >> 3); 1.887 + y1 = ly0 + (mv->row >> 3); 1.888 + 1.889 + if (x1 != lx0 && y1 != ly0) { 1.890 + constrain_line(lx0, &x1, ly0 - 1, &y1, width, height); 1.891 + vp9_blit_line(lx0, x1, ly0 - 1, y1, y_buffer, y_stride); 1.892 + 1.893 + constrain_line(lx0, &x1, ly0 + 1, &y1, width, height); 1.894 + vp9_blit_line(lx0, x1, ly0 + 1, y1, y_buffer, y_stride); 1.895 + } else { 1.896 + vp9_blit_line(lx0, x1, ly0, y1, y_buffer, y_stride); 1.897 + } 1.898 + } 1.899 + 1.900 + mi++; 1.901 + } 1.902 + mi++; 1.903 + } 1.904 + } 1.905 + 1.906 + /* Color in block modes */ 1.907 + if ((flags & VP9D_DEBUG_CLR_BLK_MODES) 1.908 + && (ppflags->display_mb_modes_flag || ppflags->display_b_modes_flag)) { 1.909 + int y, x; 1.910 + YV12_BUFFER_CONFIG *post = &cm->post_proc_buffer; 1.911 + int width = post->y_width; 1.912 + int height = post->y_height; 1.913 + uint8_t *y_ptr = cm->post_proc_buffer.y_buffer; 1.914 + uint8_t *u_ptr = cm->post_proc_buffer.u_buffer; 1.915 + uint8_t *v_ptr = cm->post_proc_buffer.v_buffer; 1.916 + int y_stride = cm->post_proc_buffer.y_stride; 1.917 + MODE_INFO *mi = cm->mi; 1.918 + 1.919 + for (y = 0; y < height; y += 16) { 1.920 + for (x = 0; x < width; x += 16) { 1.921 + int Y = 0, U = 0, V = 0; 1.922 + 1.923 + if (mi->mbmi.mode == I4X4_PRED && 1.924 + ((ppflags->display_mb_modes_flag & I4X4_PRED) || 1.925 + ppflags->display_b_modes_flag)) { 1.926 + int by, bx; 1.927 + uint8_t *yl, *ul, *vl; 1.928 + union b_mode_info *bmi = mi->bmi; 1.929 + 1.930 + yl = y_ptr + x; 1.931 + ul = u_ptr + (x >> 1); 1.932 + vl = v_ptr + (x >> 1); 1.933 + 1.934 + for (by = 0; by < 16; by += 4) { 1.935 + for (bx = 0; bx < 16; bx += 4) { 1.936 + if ((ppflags->display_b_modes_flag & (1 << mi->mbmi.mode)) 1.937 + || (ppflags->display_mb_modes_flag & I4X4_PRED)) { 1.938 + Y = B_PREDICTION_MODE_colors[bmi->as_mode][0]; 1.939 + U = B_PREDICTION_MODE_colors[bmi->as_mode][1]; 1.940 + V = B_PREDICTION_MODE_colors[bmi->as_mode][2]; 1.941 + 1.942 + vp9_blend_b(yl + bx, ul + (bx >> 1), vl + (bx >> 1), Y, U, V, 1.943 + 0xc000, y_stride); 1.944 + } 1.945 + bmi++; 1.946 + } 1.947 + 1.948 + yl += y_stride * 4; 1.949 + ul += y_stride * 1; 1.950 + vl += y_stride * 1; 1.951 + } 1.952 + } else if (ppflags->display_mb_modes_flag & (1 << mi->mbmi.mode)) { 1.953 + Y = MB_PREDICTION_MODE_colors[mi->mbmi.mode][0]; 1.954 + U = MB_PREDICTION_MODE_colors[mi->mbmi.mode][1]; 1.955 + V = MB_PREDICTION_MODE_colors[mi->mbmi.mode][2]; 1.956 + 1.957 + vp9_blend_mb_inner(y_ptr + x, u_ptr + (x >> 1), v_ptr + (x >> 1), 1.958 + Y, U, V, 0xc000, y_stride); 1.959 + } 1.960 + 1.961 + mi++; 1.962 + } 1.963 + y_ptr += y_stride * 16; 1.964 + u_ptr += y_stride * 4; 1.965 + v_ptr += y_stride * 4; 1.966 + 1.967 + mi++; 1.968 + } 1.969 + } 1.970 + 1.971 + /* Color in frame reference blocks */ 1.972 + if ((flags & VP9D_DEBUG_CLR_FRM_REF_BLKS) && 1.973 + ppflags->display_ref_frame_flag) { 1.974 + int y, x; 1.975 + YV12_BUFFER_CONFIG *post = &cm->post_proc_buffer; 1.976 + int width = post->y_width; 1.977 + int height = post->y_height; 1.978 + uint8_t *y_ptr = cm->post_proc_buffer.y_buffer; 1.979 + uint8_t *u_ptr = cm->post_proc_buffer.u_buffer; 1.980 + uint8_t *v_ptr = cm->post_proc_buffer.v_buffer; 1.981 + int y_stride = cm->post_proc_buffer.y_stride; 1.982 + MODE_INFO *mi = cm->mi; 1.983 + 1.984 + for (y = 0; y < height; y += 16) { 1.985 + for (x = 0; x < width; x += 16) { 1.986 + int Y = 0, U = 0, V = 0; 1.987 + 1.988 + if (ppflags->display_ref_frame_flag & (1 << mi->mbmi.ref_frame)) { 1.989 + Y = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][0]; 1.990 + U = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][1]; 1.991 + V = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][2]; 1.992 + 1.993 + vp9_blend_mb_outer(y_ptr + x, u_ptr + (x >> 1), v_ptr + (x >> 1), 1.994 + Y, U, V, 0xc000, y_stride); 1.995 + } 1.996 + 1.997 + mi++; 1.998 + } 1.999 + y_ptr += y_stride * 16; 1.1000 + u_ptr += y_stride * 4; 1.1001 + v_ptr += y_stride * 4; 1.1002 + 1.1003 + mi++; 1.1004 + } 1.1005 + } 1.1006 +#endif 1.1007 + 1.1008 + *dest = cm->post_proc_buffer; 1.1009 + 1.1010 + /* handle problem with extending borders */ 1.1011 + dest->y_width = cm->width; 1.1012 + dest->y_height = cm->height; 1.1013 + dest->uv_width = dest->y_width >> cm->subsampling_x; 1.1014 + dest->uv_height = dest->y_height >> cm->subsampling_y; 1.1015 + 1.1016 + return 0; 1.1017 +}