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