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