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