Home | History | Annotate | Download | only in common
      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/yv12config.h"
     17 #include "vp9/common/vp9_postproc.h"
     18 #include "vp9/common/vp9_textblit.h"
     19 #include "vpx_scale/vpx_scale.h"
     20 #include "vp9/common/vp9_systemdependent.h"
     21 #include "./vp9_rtcd.h"
     22 #include "./vpx_scale_rtcd.h"
     23 
     24 #define RGB_TO_YUV(t)                                            \
     25   ( (0.257*(float)(t >> 16))  + (0.504*(float)(t >> 8 & 0xff)) + \
     26     (0.098*(float)(t & 0xff)) + 16),                             \
     27   (-(0.148*(float)(t >> 16))  - (0.291*(float)(t >> 8 & 0xff)) + \
     28     (0.439*(float)(t & 0xff)) + 128),                            \
     29   ( (0.439*(float)(t >> 16))  - (0.368*(float)(t >> 8 & 0xff)) - \
     30     (0.071*(float)(t & 0xff)) + 128)
     31 
     32 /* global constants */
     33 #if 0 && CONFIG_POSTPROC_VISUALIZER
     34 static const unsigned char MB_PREDICTION_MODE_colors[MB_MODE_COUNT][3] = {
     35   { RGB_TO_YUV(0x98FB98) },   /* PaleGreen */
     36   { RGB_TO_YUV(0x00FF00) },   /* Green */
     37   { RGB_TO_YUV(0xADFF2F) },   /* GreenYellow */
     38   { RGB_TO_YUV(0x8F0000) },   /* Dark Red */
     39   { RGB_TO_YUV(0x008F8F) },   /* Dark Cyan */
     40   { RGB_TO_YUV(0x008F8F) },   /* Dark Cyan */
     41   { RGB_TO_YUV(0x008F8F) },   /* Dark Cyan */
     42   { RGB_TO_YUV(0x8F0000) },   /* Dark Red */
     43   { RGB_TO_YUV(0x8F0000) },   /* Dark Red */
     44   { RGB_TO_YUV(0x228B22) },   /* ForestGreen */
     45   { RGB_TO_YUV(0x006400) },   /* DarkGreen */
     46   { RGB_TO_YUV(0x98F5FF) },   /* Cadet Blue */
     47   { RGB_TO_YUV(0x6CA6CD) },   /* Sky Blue */
     48   { RGB_TO_YUV(0x00008B) },   /* Dark blue */
     49   { RGB_TO_YUV(0x551A8B) },   /* Purple */
     50   { RGB_TO_YUV(0xFF0000) }    /* Red */
     51   { RGB_TO_YUV(0xCC33FF) },   /* Magenta */
     52 };
     53 
     54 static const unsigned char B_PREDICTION_MODE_colors[INTRA_MODES][3] = {
     55   { RGB_TO_YUV(0x6633ff) },   /* Purple */
     56   { RGB_TO_YUV(0xcc33ff) },   /* Magenta */
     57   { RGB_TO_YUV(0xff33cc) },   /* Pink */
     58   { RGB_TO_YUV(0xff3366) },   /* Coral */
     59   { RGB_TO_YUV(0x3366ff) },   /* Blue */
     60   { RGB_TO_YUV(0xed00f5) },   /* Dark Blue */
     61   { RGB_TO_YUV(0x2e00b8) },   /* Dark Purple */
     62   { RGB_TO_YUV(0xff6633) },   /* Orange */
     63   { RGB_TO_YUV(0x33ccff) },   /* Light Blue */
     64   { RGB_TO_YUV(0x8ab800) },   /* Green */
     65   { RGB_TO_YUV(0xffcc33) },   /* Light Orange */
     66   { RGB_TO_YUV(0x33ffcc) },   /* Aqua */
     67   { RGB_TO_YUV(0x66ff33) },   /* Light Green */
     68   { RGB_TO_YUV(0xccff33) },   /* Yellow */
     69 };
     70 
     71 static const unsigned char MV_REFERENCE_FRAME_colors[MAX_REF_FRAMES][3] = {
     72   { RGB_TO_YUV(0x00ff00) },   /* Blue */
     73   { RGB_TO_YUV(0x0000ff) },   /* Green */
     74   { RGB_TO_YUV(0xffff00) },   /* Yellow */
     75   { RGB_TO_YUV(0xff0000) },   /* Red */
     76 };
     77 #endif
     78 
     79 static const short kernel5[] = {
     80   1, 1, 4, 1, 1
     81 };
     82 
     83 const short vp9_rv[] = {
     84   8, 5, 2, 2, 8, 12, 4, 9, 8, 3,
     85   0, 3, 9, 0, 0, 0, 8, 3, 14, 4,
     86   10, 1, 11, 14, 1, 14, 9, 6, 12, 11,
     87   8, 6, 10, 0, 0, 8, 9, 0, 3, 14,
     88   8, 11, 13, 4, 2, 9, 0, 3, 9, 6,
     89   1, 2, 3, 14, 13, 1, 8, 2, 9, 7,
     90   3, 3, 1, 13, 13, 6, 6, 5, 2, 7,
     91   11, 9, 11, 8, 7, 3, 2, 0, 13, 13,
     92   14, 4, 12, 5, 12, 10, 8, 10, 13, 10,
     93   4, 14, 4, 10, 0, 8, 11, 1, 13, 7,
     94   7, 14, 6, 14, 13, 2, 13, 5, 4, 4,
     95   0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
     96   8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
     97   3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
     98   3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
     99   13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
    100   5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
    101   9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
    102   4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
    103   3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
    104   11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
    105   5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
    106   0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
    107   10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
    108   4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
    109   0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
    110   8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
    111   3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
    112   3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
    113   13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
    114   5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
    115   9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
    116   4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
    117   3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
    118   11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
    119   5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
    120   0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
    121   10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
    122   4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
    123   3, 8, 3, 7, 8, 5, 11, 4, 12, 3,
    124   11, 9, 14, 8, 14, 13, 4, 3, 1, 2,
    125   14, 6, 5, 4, 4, 11, 4, 6, 2, 1,
    126   5, 8, 8, 12, 13, 5, 14, 10, 12, 13,
    127   0, 9, 5, 5, 11, 10, 13, 9, 10, 13,
    128 };
    129 
    130 
    131 /****************************************************************************
    132  */
    133 void 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 
    209 static 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 
    216 void 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 
    254 void 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 
    286 static 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 
    314 void 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 
    340 void 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 
    374 double vp9_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 
    379 static 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)(.5 + 256 * vp9_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 
    428 /****************************************************************************
    429  *
    430  *  ROUTINE       : plane_add_noise_c
    431  *
    432  *  INPUTS        : unsigned char *Start  starting address of buffer to
    433  *                                        add gaussian noise to
    434  *                  unsigned int width    width of plane
    435  *                  unsigned int height   height of plane
    436  *                  int  pitch    distance between subsequent lines of frame
    437  *                  int  q        quantizer used to determine amount of noise
    438  *                                  to add
    439  *
    440  *  OUTPUTS       : None.
    441  *
    442  *  RETURNS       : void.
    443  *
    444  *  FUNCTION      : adds gaussian noise to a plane of pixels
    445  *
    446  *  SPECIAL NOTES : None.
    447  *
    448  ****************************************************************************/
    449 void vp9_plane_add_noise_c(uint8_t *start, char *noise,
    450                            char blackclamp[16],
    451                            char whiteclamp[16],
    452                            char bothclamp[16],
    453                            unsigned int width, unsigned int height, int pitch) {
    454   unsigned int i, j;
    455 
    456   for (i = 0; i < height; i++) {
    457     uint8_t *pos = start + i * pitch;
    458     char  *ref = (char *)(noise + (rand() & 0xff));  // NOLINT
    459 
    460     for (j = 0; j < width; j++) {
    461       if (pos[j] < blackclamp[0])
    462         pos[j] = blackclamp[0];
    463 
    464       if (pos[j] > 255 + whiteclamp[0])
    465         pos[j] = 255 + whiteclamp[0];
    466 
    467       pos[j] += ref[j];
    468     }
    469   }
    470 }
    471 
    472 /* Blend the macro block with a solid colored square.  Leave the
    473  * edges unblended to give distinction to macro blocks in areas
    474  * filled with the same color block.
    475  */
    476 void vp9_blend_mb_inner_c(uint8_t *y, uint8_t *u, uint8_t *v,
    477                           int y1, int u1, int v1, int alpha, int stride) {
    478   int i, j;
    479   int y1_const = y1 * ((1 << 16) - alpha);
    480   int u1_const = u1 * ((1 << 16) - alpha);
    481   int v1_const = v1 * ((1 << 16) - alpha);
    482 
    483   y += 2 * stride + 2;
    484   for (i = 0; i < 12; i++) {
    485     for (j = 0; j < 12; j++) {
    486       y[j] = (y[j] * alpha + y1_const) >> 16;
    487     }
    488     y += stride;
    489   }
    490 
    491   stride >>= 1;
    492 
    493   u += stride + 1;
    494   v += stride + 1;
    495 
    496   for (i = 0; i < 6; i++) {
    497     for (j = 0; j < 6; j++) {
    498       u[j] = (u[j] * alpha + u1_const) >> 16;
    499       v[j] = (v[j] * alpha + v1_const) >> 16;
    500     }
    501     u += stride;
    502     v += stride;
    503   }
    504 }
    505 
    506 /* Blend only the edge of the macro block.  Leave center
    507  * unblended to allow for other visualizations to be layered.
    508  */
    509 void vp9_blend_mb_outer_c(uint8_t *y, uint8_t *u, uint8_t *v,
    510                           int y1, int u1, int v1, int alpha, int stride) {
    511   int i, j;
    512   int y1_const = y1 * ((1 << 16) - alpha);
    513   int u1_const = u1 * ((1 << 16) - alpha);
    514   int v1_const = v1 * ((1 << 16) - alpha);
    515 
    516   for (i = 0; i < 2; i++) {
    517     for (j = 0; j < 16; j++) {
    518       y[j] = (y[j] * alpha + y1_const) >> 16;
    519     }
    520     y += stride;
    521   }
    522 
    523   for (i = 0; i < 12; i++) {
    524     y[0]  = (y[0] * alpha  + y1_const) >> 16;
    525     y[1]  = (y[1] * alpha  + y1_const) >> 16;
    526     y[14] = (y[14] * alpha + y1_const) >> 16;
    527     y[15] = (y[15] * alpha + y1_const) >> 16;
    528     y += stride;
    529   }
    530 
    531   for (i = 0; i < 2; i++) {
    532     for (j = 0; j < 16; j++) {
    533       y[j] = (y[j] * alpha + y1_const) >> 16;
    534     }
    535     y += stride;
    536   }
    537 
    538   stride >>= 1;
    539 
    540   for (j = 0; j < 8; j++) {
    541     u[j] = (u[j] * alpha + u1_const) >> 16;
    542     v[j] = (v[j] * alpha + v1_const) >> 16;
    543   }
    544   u += stride;
    545   v += stride;
    546 
    547   for (i = 0; i < 6; i++) {
    548     u[0] = (u[0] * alpha + u1_const) >> 16;
    549     v[0] = (v[0] * alpha + v1_const) >> 16;
    550 
    551     u[7] = (u[7] * alpha + u1_const) >> 16;
    552     v[7] = (v[7] * alpha + v1_const) >> 16;
    553 
    554     u += stride;
    555     v += stride;
    556   }
    557 
    558   for (j = 0; j < 8; j++) {
    559     u[j] = (u[j] * alpha + u1_const) >> 16;
    560     v[j] = (v[j] * alpha + v1_const) >> 16;
    561   }
    562 }
    563 
    564 void vp9_blend_b_c(uint8_t *y, uint8_t *u, uint8_t *v,
    565                    int y1, int u1, int v1, int alpha, int stride) {
    566   int i, j;
    567   int y1_const = y1 * ((1 << 16) - alpha);
    568   int u1_const = u1 * ((1 << 16) - alpha);
    569   int v1_const = v1 * ((1 << 16) - alpha);
    570 
    571   for (i = 0; i < 4; i++) {
    572     for (j = 0; j < 4; j++) {
    573       y[j] = (y[j] * alpha + y1_const) >> 16;
    574     }
    575     y += stride;
    576   }
    577 
    578   stride >>= 1;
    579 
    580   for (i = 0; i < 2; i++) {
    581     for (j = 0; j < 2; j++) {
    582       u[j] = (u[j] * alpha + u1_const) >> 16;
    583       v[j] = (v[j] * alpha + v1_const) >> 16;
    584     }
    585     u += stride;
    586     v += stride;
    587   }
    588 }
    589 
    590 static void constrain_line(int x0, int *x1, int y0, int *y1,
    591                            int width, int height) {
    592   int dx;
    593   int dy;
    594 
    595   if (*x1 > width) {
    596     dx = *x1 - x0;
    597     dy = *y1 - y0;
    598 
    599     *x1 = width;
    600     if (dx)
    601       *y1 = ((width - x0) * dy) / dx + y0;
    602   }
    603   if (*x1 < 0) {
    604     dx = *x1 - x0;
    605     dy = *y1 - y0;
    606 
    607     *x1 = 0;
    608     if (dx)
    609       *y1 = ((0 - x0) * dy) / dx + y0;
    610   }
    611   if (*y1 > height) {
    612     dx = *x1 - x0;
    613     dy = *y1 - y0;
    614 
    615     *y1 = height;
    616     if (dy)
    617       *x1 = ((height - y0) * dx) / dy + x0;
    618   }
    619   if (*y1 < 0) {
    620     dx = *x1 - x0;
    621     dy = *y1 - y0;
    622 
    623     *y1 = 0;
    624     if (dy)
    625       *x1 = ((0 - y0) * dx) / dy + x0;
    626   }
    627 }
    628 
    629 int vp9_post_proc_frame(struct VP9Common *cm,
    630                         YV12_BUFFER_CONFIG *dest, vp9_ppflags_t *ppflags) {
    631   int q = cm->lf.filter_level * 10 / 6;
    632   int flags = ppflags->post_proc_flag;
    633   int deblock_level = ppflags->deblocking_level;
    634   int noise_level = ppflags->noise_level;
    635 
    636   if (!cm->frame_to_show)
    637     return -1;
    638 
    639   if (q > 63)
    640     q = 63;
    641 
    642   if (!flags) {
    643     *dest = *cm->frame_to_show;
    644     return 0;
    645   }
    646 
    647 #if ARCH_X86||ARCH_X86_64
    648   vpx_reset_mmx_state();
    649 #endif
    650 
    651   if (flags & VP9D_DEMACROBLOCK) {
    652     deblock_and_de_macro_block(cm->frame_to_show, &cm->post_proc_buffer,
    653                                q + (deblock_level - 5) * 10, 1, 0);
    654   } else if (flags & VP9D_DEBLOCK) {
    655     vp9_deblock(cm->frame_to_show, &cm->post_proc_buffer, q);
    656   } else {
    657     vp8_yv12_copy_frame(cm->frame_to_show, &cm->post_proc_buffer);
    658   }
    659 
    660   if (flags & VP9D_ADDNOISE) {
    661     if (cm->postproc_state.last_q != q
    662         || cm->postproc_state.last_noise != noise_level) {
    663       fillrd(&cm->postproc_state, 63 - q, noise_level);
    664     }
    665 
    666     vp9_plane_add_noise(cm->post_proc_buffer.y_buffer,
    667                         cm->postproc_state.noise,
    668                         cm->postproc_state.blackclamp,
    669                         cm->postproc_state.whiteclamp,
    670                         cm->postproc_state.bothclamp,
    671                         cm->post_proc_buffer.y_width,
    672                         cm->post_proc_buffer.y_height,
    673                         cm->post_proc_buffer.y_stride);
    674   }
    675 
    676 #if 0 && CONFIG_POSTPROC_VISUALIZER
    677   if (flags & VP9D_DEBUG_TXT_FRAME_INFO) {
    678     char message[512];
    679     snprintf(message, sizeof(message) -1,
    680              "F%1dG%1dQ%3dF%3dP%d_s%dx%d",
    681              (cm->frame_type == KEY_FRAME),
    682              cm->refresh_golden_frame,
    683              cm->base_qindex,
    684              cm->filter_level,
    685              flags,
    686              cm->mb_cols, cm->mb_rows);
    687     vp9_blit_text(message, cm->post_proc_buffer.y_buffer,
    688                   cm->post_proc_buffer.y_stride);
    689   }
    690 
    691   if (flags & VP9D_DEBUG_TXT_MBLK_MODES) {
    692     int i, j;
    693     uint8_t *y_ptr;
    694     YV12_BUFFER_CONFIG *post = &cm->post_proc_buffer;
    695     int mb_rows = post->y_height >> 4;
    696     int mb_cols = post->y_width  >> 4;
    697     int mb_index = 0;
    698     MODE_INFO *mi = cm->mi;
    699 
    700     y_ptr = post->y_buffer + 4 * post->y_stride + 4;
    701 
    702     /* vp9_filter each macro block */
    703     for (i = 0; i < mb_rows; i++) {
    704       for (j = 0; j < mb_cols; j++) {
    705         char zz[4];
    706 
    707         snprintf(zz, sizeof(zz) - 1, "%c", mi[mb_index].mbmi.mode + 'a');
    708 
    709         vp9_blit_text(zz, y_ptr, post->y_stride);
    710         mb_index++;
    711         y_ptr += 16;
    712       }
    713 
    714       mb_index++; /* border */
    715       y_ptr += post->y_stride  * 16 - post->y_width;
    716     }
    717   }
    718 
    719   if (flags & VP9D_DEBUG_TXT_DC_DIFF) {
    720     int i, j;
    721     uint8_t *y_ptr;
    722     YV12_BUFFER_CONFIG *post = &cm->post_proc_buffer;
    723     int mb_rows = post->y_height >> 4;
    724     int mb_cols = post->y_width  >> 4;
    725     int mb_index = 0;
    726     MODE_INFO *mi = cm->mi;
    727 
    728     y_ptr = post->y_buffer + 4 * post->y_stride + 4;
    729 
    730     /* vp9_filter each macro block */
    731     for (i = 0; i < mb_rows; i++) {
    732       for (j = 0; j < mb_cols; j++) {
    733         char zz[4];
    734         int dc_diff = !(mi[mb_index].mbmi.mode != I4X4_PRED &&
    735                         mi[mb_index].mbmi.mode != SPLITMV &&
    736                         mi[mb_index].mbmi.skip_coeff);
    737 
    738         if (cm->frame_type == KEY_FRAME)
    739           snprintf(zz, sizeof(zz) - 1, "a");
    740         else
    741           snprintf(zz, sizeof(zz) - 1, "%c", dc_diff + '0');
    742 
    743         vp9_blit_text(zz, y_ptr, post->y_stride);
    744         mb_index++;
    745         y_ptr += 16;
    746       }
    747 
    748       mb_index++; /* border */
    749       y_ptr += post->y_stride  * 16 - post->y_width;
    750     }
    751   }
    752 
    753   if (flags & VP9D_DEBUG_TXT_RATE_INFO) {
    754     char message[512];
    755     snprintf(message, sizeof(message),
    756              "Bitrate: %10.2f framerate: %10.2f ",
    757              cm->bitrate, cm->framerate);
    758     vp9_blit_text(message, cm->post_proc_buffer.y_buffer,
    759                   cm->post_proc_buffer.y_stride);
    760   }
    761 
    762   /* Draw motion vectors */
    763   if ((flags & VP9D_DEBUG_DRAW_MV) && ppflags->display_mv_flag) {
    764     YV12_BUFFER_CONFIG *post = &cm->post_proc_buffer;
    765     int width  = post->y_width;
    766     int height = post->y_height;
    767     uint8_t *y_buffer = cm->post_proc_buffer.y_buffer;
    768     int y_stride = cm->post_proc_buffer.y_stride;
    769     MODE_INFO *mi = cm->mi;
    770     int x0, y0;
    771 
    772     for (y0 = 0; y0 < height; y0 += 16) {
    773       for (x0 = 0; x0 < width; x0 += 16) {
    774         int x1, y1;
    775 
    776         if (!(ppflags->display_mv_flag & (1 << mi->mbmi.mode))) {
    777           mi++;
    778           continue;
    779         }
    780 
    781         if (mi->mbmi.mode == SPLITMV) {
    782           switch (mi->mbmi.partitioning) {
    783             case PARTITIONING_16X8 : {  /* mv_top_bottom */
    784               union b_mode_info *bmi = &mi->bmi[0];
    785               MV *mv = &bmi->mv.as_mv;
    786 
    787               x1 = x0 + 8 + (mv->col >> 3);
    788               y1 = y0 + 4 + (mv->row >> 3);
    789 
    790               constrain_line(x0 + 8, &x1, y0 + 4, &y1, width, height);
    791               vp9_blit_line(x0 + 8,  x1, y0 + 4,  y1, y_buffer, y_stride);
    792 
    793               bmi = &mi->bmi[8];
    794 
    795               x1 = x0 + 8 + (mv->col >> 3);
    796               y1 = y0 + 12 + (mv->row >> 3);
    797 
    798               constrain_line(x0 + 8, &x1, y0 + 12, &y1, width, height);
    799               vp9_blit_line(x0 + 8,  x1, y0 + 12,  y1, y_buffer, y_stride);
    800 
    801               break;
    802             }
    803             case PARTITIONING_8X16 : {  /* mv_left_right */
    804               union b_mode_info *bmi = &mi->bmi[0];
    805               MV *mv = &bmi->mv.as_mv;
    806 
    807               x1 = x0 + 4 + (mv->col >> 3);
    808               y1 = y0 + 8 + (mv->row >> 3);
    809 
    810               constrain_line(x0 + 4, &x1, y0 + 8, &y1, width, height);
    811               vp9_blit_line(x0 + 4,  x1, y0 + 8,  y1, y_buffer, y_stride);
    812 
    813               bmi = &mi->bmi[2];
    814 
    815               x1 = x0 + 12 + (mv->col >> 3);
    816               y1 = y0 + 8 + (mv->row >> 3);
    817 
    818               constrain_line(x0 + 12, &x1, y0 + 8, &y1, width, height);
    819               vp9_blit_line(x0 + 12,  x1, y0 + 8,  y1, y_buffer, y_stride);
    820 
    821               break;
    822             }
    823             case PARTITIONING_8X8 : {  /* mv_quarters   */
    824               union b_mode_info *bmi = &mi->bmi[0];
    825               MV *mv = &bmi->mv.as_mv;
    826 
    827               x1 = x0 + 4 + (mv->col >> 3);
    828               y1 = y0 + 4 + (mv->row >> 3);
    829 
    830               constrain_line(x0 + 4, &x1, y0 + 4, &y1, width, height);
    831               vp9_blit_line(x0 + 4,  x1, y0 + 4,  y1, y_buffer, y_stride);
    832 
    833               bmi = &mi->bmi[2];
    834 
    835               x1 = x0 + 12 + (mv->col >> 3);
    836               y1 = y0 + 4 + (mv->row >> 3);
    837 
    838               constrain_line(x0 + 12, &x1, y0 + 4, &y1, width, height);
    839               vp9_blit_line(x0 + 12,  x1, y0 + 4,  y1, y_buffer, y_stride);
    840 
    841               bmi = &mi->bmi[8];
    842 
    843               x1 = x0 + 4 + (mv->col >> 3);
    844               y1 = y0 + 12 + (mv->row >> 3);
    845 
    846               constrain_line(x0 + 4, &x1, y0 + 12, &y1, width, height);
    847               vp9_blit_line(x0 + 4,  x1, y0 + 12,  y1, y_buffer, y_stride);
    848 
    849               bmi = &mi->bmi[10];
    850 
    851               x1 = x0 + 12 + (mv->col >> 3);
    852               y1 = y0 + 12 + (mv->row >> 3);
    853 
    854               constrain_line(x0 + 12, &x1, y0 + 12, &y1, width, height);
    855               vp9_blit_line(x0 + 12,  x1, y0 + 12,  y1, y_buffer, y_stride);
    856               break;
    857             }
    858             case PARTITIONING_4X4:
    859             default : {
    860               union b_mode_info *bmi = mi->bmi;
    861               int bx0, by0;
    862 
    863               for (by0 = y0; by0 < (y0 + 16); by0 += 4) {
    864                 for (bx0 = x0; bx0 < (x0 + 16); bx0 += 4) {
    865                   MV *mv = &bmi->mv.as_mv;
    866 
    867                   x1 = bx0 + 2 + (mv->col >> 3);
    868                   y1 = by0 + 2 + (mv->row >> 3);
    869 
    870                   constrain_line(bx0 + 2, &x1, by0 + 2, &y1, width, height);
    871                   vp9_blit_line(bx0 + 2,  x1, by0 + 2,  y1, y_buffer, y_stride);
    872 
    873                   bmi++;
    874                 }
    875               }
    876             }
    877           }
    878         } else if (is_inter_mode(mi->mbmi.mode)) {
    879           MV *mv = &mi->mbmi.mv.as_mv;
    880           const int lx0 = x0 + 8;
    881           const int ly0 = y0 + 8;
    882 
    883           x1 = lx0 + (mv->col >> 3);
    884           y1 = ly0 + (mv->row >> 3);
    885 
    886           if (x1 != lx0 && y1 != ly0) {
    887             constrain_line(lx0, &x1, ly0 - 1, &y1, width, height);
    888             vp9_blit_line(lx0,  x1, ly0 - 1,  y1, y_buffer, y_stride);
    889 
    890             constrain_line(lx0, &x1, ly0 + 1, &y1, width, height);
    891             vp9_blit_line(lx0,  x1, ly0 + 1,  y1, y_buffer, y_stride);
    892           } else {
    893             vp9_blit_line(lx0,  x1, ly0,  y1, y_buffer, y_stride);
    894           }
    895         }
    896 
    897         mi++;
    898       }
    899       mi++;
    900     }
    901   }
    902 
    903   /* Color in block modes */
    904   if ((flags & VP9D_DEBUG_CLR_BLK_MODES)
    905       && (ppflags->display_mb_modes_flag || ppflags->display_b_modes_flag)) {
    906     int y, x;
    907     YV12_BUFFER_CONFIG *post = &cm->post_proc_buffer;
    908     int width  = post->y_width;
    909     int height = post->y_height;
    910     uint8_t *y_ptr = cm->post_proc_buffer.y_buffer;
    911     uint8_t *u_ptr = cm->post_proc_buffer.u_buffer;
    912     uint8_t *v_ptr = cm->post_proc_buffer.v_buffer;
    913     int y_stride = cm->post_proc_buffer.y_stride;
    914     MODE_INFO *mi = cm->mi;
    915 
    916     for (y = 0; y < height; y += 16) {
    917       for (x = 0; x < width; x += 16) {
    918         int Y = 0, U = 0, V = 0;
    919 
    920         if (mi->mbmi.mode == I4X4_PRED &&
    921             ((ppflags->display_mb_modes_flag & I4X4_PRED) ||
    922              ppflags->display_b_modes_flag)) {
    923           int by, bx;
    924           uint8_t *yl, *ul, *vl;
    925           union b_mode_info *bmi = mi->bmi;
    926 
    927           yl = y_ptr + x;
    928           ul = u_ptr + (x >> 1);
    929           vl = v_ptr + (x >> 1);
    930 
    931           for (by = 0; by < 16; by += 4) {
    932             for (bx = 0; bx < 16; bx += 4) {
    933               if ((ppflags->display_b_modes_flag & (1 << mi->mbmi.mode))
    934                   || (ppflags->display_mb_modes_flag & I4X4_PRED)) {
    935                 Y = B_PREDICTION_MODE_colors[bmi->as_mode][0];
    936                 U = B_PREDICTION_MODE_colors[bmi->as_mode][1];
    937                 V = B_PREDICTION_MODE_colors[bmi->as_mode][2];
    938 
    939                 vp9_blend_b(yl + bx, ul + (bx >> 1), vl + (bx >> 1), Y, U, V,
    940                     0xc000, y_stride);
    941               }
    942               bmi++;
    943             }
    944 
    945             yl += y_stride * 4;
    946             ul += y_stride * 1;
    947             vl += y_stride * 1;
    948           }
    949         } else if (ppflags->display_mb_modes_flag & (1 << mi->mbmi.mode)) {
    950           Y = MB_PREDICTION_MODE_colors[mi->mbmi.mode][0];
    951           U = MB_PREDICTION_MODE_colors[mi->mbmi.mode][1];
    952           V = MB_PREDICTION_MODE_colors[mi->mbmi.mode][2];
    953 
    954           vp9_blend_mb_inner(y_ptr + x, u_ptr + (x >> 1), v_ptr + (x >> 1),
    955                              Y, U, V, 0xc000, y_stride);
    956         }
    957 
    958         mi++;
    959       }
    960       y_ptr += y_stride * 16;
    961       u_ptr += y_stride * 4;
    962       v_ptr += y_stride * 4;
    963 
    964       mi++;
    965     }
    966   }
    967 
    968   /* Color in frame reference blocks */
    969   if ((flags & VP9D_DEBUG_CLR_FRM_REF_BLKS) &&
    970       ppflags->display_ref_frame_flag) {
    971     int y, x;
    972     YV12_BUFFER_CONFIG *post = &cm->post_proc_buffer;
    973     int width  = post->y_width;
    974     int height = post->y_height;
    975     uint8_t *y_ptr = cm->post_proc_buffer.y_buffer;
    976     uint8_t *u_ptr = cm->post_proc_buffer.u_buffer;
    977     uint8_t *v_ptr = cm->post_proc_buffer.v_buffer;
    978     int y_stride = cm->post_proc_buffer.y_stride;
    979     MODE_INFO *mi = cm->mi;
    980 
    981     for (y = 0; y < height; y += 16) {
    982       for (x = 0; x < width; x += 16) {
    983         int Y = 0, U = 0, V = 0;
    984 
    985         if (ppflags->display_ref_frame_flag & (1 << mi->mbmi.ref_frame)) {
    986           Y = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][0];
    987           U = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][1];
    988           V = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][2];
    989 
    990           vp9_blend_mb_outer(y_ptr + x, u_ptr + (x >> 1), v_ptr + (x >> 1),
    991                              Y, U, V, 0xc000, y_stride);
    992         }
    993 
    994         mi++;
    995       }
    996       y_ptr += y_stride * 16;
    997       u_ptr += y_stride * 4;
    998       v_ptr += y_stride * 4;
    999 
   1000       mi++;
   1001     }
   1002   }
   1003 #endif
   1004 
   1005   *dest = cm->post_proc_buffer;
   1006 
   1007   /* handle problem with extending borders */
   1008   dest->y_width = cm->width;
   1009   dest->y_height = cm->height;
   1010   dest->uv_width = dest->y_width >> cm->subsampling_x;
   1011   dest->uv_height = dest->y_height >> cm->subsampling_y;
   1012 
   1013   return 0;
   1014 }
   1015