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