media/libvpx/vp8/common/postproc.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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  */
    12 #include "vpx_config.h"
    13 #include "vp8_rtcd.h"
    14 #include "vpx_scale_rtcd.h"
    15 #include "vpx_scale/yv12config.h"
    16 #include "postproc.h"
    17 #include "common.h"
    18 #include "vpx_scale/vpx_scale.h"
    19 #include "systemdependent.h"
    21 #include <limits.h>
    22 #include <math.h>
    23 #include <stdlib.h>
    24 #include <stdio.h>
    26 #define RGB_TO_YUV(t)                                                                       \
    27     ( (0.257*(float)(t>>16)) + (0.504*(float)(t>>8&0xff)) + (0.098*(float)(t&0xff)) + 16),  \
    28     (-(0.148*(float)(t>>16)) - (0.291*(float)(t>>8&0xff)) + (0.439*(float)(t&0xff)) + 128), \
    29     ( (0.439*(float)(t>>16)) - (0.368*(float)(t>>8&0xff)) - (0.071*(float)(t&0xff)) + 128)
    31 /* global constants */
    32 #if CONFIG_POSTPROC_VISUALIZER
    33 static const unsigned char MB_PREDICTION_MODE_colors[MB_MODE_COUNT][3] =
    34 {
    35     { RGB_TO_YUV(0x98FB98) },   /* PaleGreen */
    36     { RGB_TO_YUV(0x00FF00) },   /* Green */
    37     { RGB_TO_YUV(0xADFF2F) },   /* GreenYellow */
    38     { RGB_TO_YUV(0x228B22) },   /* ForestGreen */
    39     { RGB_TO_YUV(0x006400) },   /* DarkGreen */
    40     { RGB_TO_YUV(0x98F5FF) },   /* Cadet Blue */
    41     { RGB_TO_YUV(0x6CA6CD) },   /* Sky Blue */
    42     { RGB_TO_YUV(0x00008B) },   /* Dark blue */
    43     { RGB_TO_YUV(0x551A8B) },   /* Purple */
    44     { RGB_TO_YUV(0xFF0000) }    /* Red */
    45 };
    47 static const unsigned char B_PREDICTION_MODE_colors[B_MODE_COUNT][3] =
    48 {
    49     { RGB_TO_YUV(0x6633ff) },   /* Purple */
    50     { RGB_TO_YUV(0xcc33ff) },   /* Magenta */
    51     { RGB_TO_YUV(0xff33cc) },   /* Pink */
    52     { RGB_TO_YUV(0xff3366) },   /* Coral */
    53     { RGB_TO_YUV(0x3366ff) },   /* Blue */
    54     { RGB_TO_YUV(0xed00f5) },   /* Dark Blue */
    55     { RGB_TO_YUV(0x2e00b8) },   /* Dark Purple */
    56     { RGB_TO_YUV(0xff6633) },   /* Orange */
    57     { RGB_TO_YUV(0x33ccff) },   /* Light Blue */
    58     { RGB_TO_YUV(0x8ab800) },   /* Green */
    59     { RGB_TO_YUV(0xffcc33) },   /* Light Orange */
    60     { RGB_TO_YUV(0x33ffcc) },   /* Aqua */
    61     { RGB_TO_YUV(0x66ff33) },   /* Light Green */
    62     { RGB_TO_YUV(0xccff33) },   /* Yellow */
    63 };
    65 static const unsigned char MV_REFERENCE_FRAME_colors[MAX_REF_FRAMES][3] =
    66 {
    67     { RGB_TO_YUV(0x00ff00) },   /* Blue */
    68     { RGB_TO_YUV(0x0000ff) },   /* Green */
    69     { RGB_TO_YUV(0xffff00) },   /* Yellow */
    70     { RGB_TO_YUV(0xff0000) },   /* Red */
    71 };
    72 #endif
    74 static const short kernel5[] =
    75 {
    76     1, 1, 4, 1, 1
    77 };
    79 const short vp8_rv[] =
    80 {
    81     8, 5, 2, 2, 8, 12, 4, 9, 8, 3,
    82     0, 3, 9, 0, 0, 0, 8, 3, 14, 4,
    83     10, 1, 11, 14, 1, 14, 9, 6, 12, 11,
    84     8, 6, 10, 0, 0, 8, 9, 0, 3, 14,
    85     8, 11, 13, 4, 2, 9, 0, 3, 9, 6,
    86     1, 2, 3, 14, 13, 1, 8, 2, 9, 7,
    87     3, 3, 1, 13, 13, 6, 6, 5, 2, 7,
    88     11, 9, 11, 8, 7, 3, 2, 0, 13, 13,
    89     14, 4, 12, 5, 12, 10, 8, 10, 13, 10,
    90     4, 14, 4, 10, 0, 8, 11, 1, 13, 7,
    91     7, 14, 6, 14, 13, 2, 13, 5, 4, 4,
    92     0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
    93     8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
    94     3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
    95     3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
    96     13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
    97     5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
    98     9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
    99     4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
   100     3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
   101     11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
   102     5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
   103     0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
   104     10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
   105     4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
   106     0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
   107     8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
   108     3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
   109     3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
   110     13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
   111     5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
   112     9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
   113     4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
   114     3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
   115     11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
   116     5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
   117     0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
   118     10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
   119     4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
   120     3, 8, 3, 7, 8, 5, 11, 4, 12, 3,
   121     11, 9, 14, 8, 14, 13, 4, 3, 1, 2,
   122     14, 6, 5, 4, 4, 11, 4, 6, 2, 1,
   123     5, 8, 8, 12, 13, 5, 14, 10, 12, 13,
   124     0, 9, 5, 5, 11, 10, 13, 9, 10, 13,
   125 };
   127 extern void vp8_blit_text(const char *msg, unsigned char *address, const int pitch);
   128 extern void vp8_blit_line(int x0, int x1, int y0, int y1, unsigned char *image, const int pitch);
   129 /***********************************************************************************************************
   130  */
   131 void vp8_post_proc_down_and_across_mb_row_c
   132 (
   133     unsigned char *src_ptr,
   134     unsigned char *dst_ptr,
   135     int src_pixels_per_line,
   136     int dst_pixels_per_line,
   137     int cols,
   138     unsigned char *f,
   139     int size
   140 )
   141 {
   142     unsigned char *p_src, *p_dst;
   143     int row;
   144     int col;
   145     unsigned char v;
   146     unsigned char d[4];
   148     for (row = 0; row < size; row++)
   149     {
   150         /* post_proc_down for one row */
   151         p_src = src_ptr;
   152         p_dst = dst_ptr;
   154         for (col = 0; col < cols; col++)
   155         {
   156             unsigned char p_above2 = p_src[col - 2 * src_pixels_per_line];
   157             unsigned char p_above1 = p_src[col - src_pixels_per_line];
   158             unsigned char p_below1 = p_src[col + src_pixels_per_line];
   159             unsigned char p_below2 = p_src[col + 2 * src_pixels_per_line];
   161             v = p_src[col];
   163             if ((abs(v - p_above2) < f[col]) && (abs(v - p_above1) < f[col])
   164                 && (abs(v - p_below1) < f[col]) && (abs(v - p_below2) < f[col]))
   165             {
   166                 unsigned char k1, k2, k3;
   167                 k1 = (p_above2 + p_above1 + 1) >> 1;
   168                 k2 = (p_below2 + p_below1 + 1) >> 1;
   169                 k3 = (k1 + k2 + 1) >> 1;
   170                 v = (k3 + v + 1) >> 1;
   171             }
   173             p_dst[col] = v;
   174         }
   176         /* now post_proc_across */
   177         p_src = dst_ptr;
   178         p_dst = dst_ptr;
   180         p_src[-2] = p_src[-1] = p_src[0];
   181         p_src[cols] = p_src[cols + 1] = p_src[cols - 1];
   183         for (col = 0; col < cols; col++)
   184         {
   185             v = p_src[col];
   187             if ((abs(v - p_src[col - 2]) < f[col])
   188                 && (abs(v - p_src[col - 1]) < f[col])
   189                 && (abs(v - p_src[col + 1]) < f[col])
   190                 && (abs(v - p_src[col + 2]) < f[col]))
   191             {
   192                 unsigned char k1, k2, k3;
   193                 k1 = (p_src[col - 2] + p_src[col - 1] + 1) >> 1;
   194                 k2 = (p_src[col + 2] + p_src[col + 1] + 1) >> 1;
   195                 k3 = (k1 + k2 + 1) >> 1;
   196                 v = (k3 + v + 1) >> 1;
   197             }
   199             d[col & 3] = v;
   201             if (col >= 2)
   202                 p_dst[col - 2] = d[(col - 2) & 3];
   203         }
   205         /* handle the last two pixels */
   206         p_dst[col - 2] = d[(col - 2) & 3];
   207         p_dst[col - 1] = d[(col - 1) & 3];
   209         /* next row */
   210         src_ptr += src_pixels_per_line;
   211         dst_ptr += dst_pixels_per_line;
   212     }
   213 }
   215 static int q2mbl(int x)
   216 {
   217     if (x < 20) x = 20;
   219     x = 50 + (x - 50) * 10 / 8;
   220     return x * x / 3;
   221 }
   222 void vp8_mbpost_proc_across_ip_c(unsigned char *src, int pitch, int rows, int cols, int flimit)
   223 {
   224     int r, c, i;
   226     unsigned char *s = src;
   227     unsigned char d[16];
   229     for (r = 0; r < rows; r++)
   230     {
   231         int sumsq = 0;
   232         int sum   = 0;
   234         for (i = -8; i<0; i++)
   235           s[i]=s[0];
   237         /* 17 avoids valgrind warning - we buffer values in c in d
   238          * and only write them when we've read 8 ahead...
   239          */
   240         for (i = cols; i<cols+17; i++)
   241           s[i]=s[cols-1];
   243         for (i = -8; i <= 6; i++)
   244         {
   245             sumsq += s[i] * s[i];
   246             sum   += s[i];
   247             d[i+8] = 0;
   248         }
   250         for (c = 0; c < cols + 8; c++)
   251         {
   252             int x = s[c+7] - s[c-8];
   253             int y = s[c+7] + s[c-8];
   255             sum  += x;
   256             sumsq += x * y;
   258             d[c&15] = s[c];
   260             if (sumsq * 15 - sum * sum < flimit)
   261             {
   262                 d[c&15] = (8 + sum + s[c]) >> 4;
   263             }
   265             s[c-8] = d[(c-8)&15];
   266         }
   268         s += pitch;
   269     }
   270 }
   273 void vp8_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols, int flimit)
   274 {
   275     int r, c, i;
   276     const short *rv3 = &vp8_rv[63&rand()];
   278     for (c = 0; c < cols; c++ )
   279     {
   280         unsigned char *s = &dst[c];
   281         int sumsq = 0;
   282         int sum   = 0;
   283         unsigned char d[16];
   284         const short *rv2 = rv3 + ((c * 17) & 127);
   286         for (i = -8; i < 0; i++)
   287           s[i*pitch]=s[0];
   289         /* 17 avoids valgrind warning - we buffer values in c in d
   290          * and only write them when we've read 8 ahead...
   291          */
   292         for (i = rows; i < rows+17; i++)
   293           s[i*pitch]=s[(rows-1)*pitch];
   295         for (i = -8; i <= 6; i++)
   296         {
   297             sumsq += s[i*pitch] * s[i*pitch];
   298             sum   += s[i*pitch];
   299         }
   301         for (r = 0; r < rows + 8; r++)
   302         {
   303             sumsq += s[7*pitch] * s[ 7*pitch] - s[-8*pitch] * s[-8*pitch];
   304             sum  += s[7*pitch] - s[-8*pitch];
   305             d[r&15] = s[0];
   307             if (sumsq * 15 - sum * sum < flimit)
   308             {
   309                 d[r&15] = (rv2[r&127] + sum + s[0]) >> 4;
   310             }
   312             s[-8*pitch] = d[(r-8)&15];
   313             s += pitch;
   314         }
   315     }
   316 }
   318 static void vp8_de_mblock(YV12_BUFFER_CONFIG         *post,
   319                           int                         q)
   320 {
   321     vp8_mbpost_proc_across_ip(post->y_buffer, post->y_stride, post->y_height,
   322                               post->y_width, q2mbl(q));
   323     vp8_mbpost_proc_down(post->y_buffer, post->y_stride, post->y_height,
   324                          post->y_width, q2mbl(q));
   325 }
   327 void vp8_deblock(VP8_COMMON                 *cm,
   328                  YV12_BUFFER_CONFIG         *source,
   329                  YV12_BUFFER_CONFIG         *post,
   330                  int                         q,
   331                  int                         low_var_thresh,
   332                  int                         flag)
   333 {
   334     double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
   335     int ppl = (int)(level + .5);
   337     const MODE_INFO *mode_info_context = cm->show_frame_mi;
   338     int mbr, mbc;
   340     /* The pixel thresholds are adjusted according to if or not the macroblock
   341      * is a skipped block.  */
   342     unsigned char *ylimits = cm->pp_limits_buffer;
   343     unsigned char *uvlimits = cm->pp_limits_buffer + 16 * cm->mb_cols;
   344     (void) low_var_thresh;
   345     (void) flag;
   347     if (ppl > 0)
   348     {
   349         for (mbr = 0; mbr < cm->mb_rows; mbr++)
   350         {
   351             unsigned char *ylptr = ylimits;
   352             unsigned char *uvlptr = uvlimits;
   353             for (mbc = 0; mbc < cm->mb_cols; mbc++)
   354             {
   355                 unsigned char mb_ppl;
   357                 if (mode_info_context->mbmi.mb_skip_coeff)
   358                     mb_ppl = (unsigned char)ppl >> 1;
   359                 else
   360                     mb_ppl = (unsigned char)ppl;
   362                 vpx_memset(ylptr, mb_ppl, 16);
   363                 vpx_memset(uvlptr, mb_ppl, 8);
   365                 ylptr += 16;
   366                 uvlptr += 8;
   367                 mode_info_context++;
   368             }
   369             mode_info_context++;
   371             vp8_post_proc_down_and_across_mb_row(
   372                 source->y_buffer + 16 * mbr * source->y_stride,
   373                 post->y_buffer + 16 * mbr * post->y_stride, source->y_stride,
   374                 post->y_stride, source->y_width, ylimits, 16);
   376             vp8_post_proc_down_and_across_mb_row(
   377                 source->u_buffer + 8 * mbr * source->uv_stride,
   378                 post->u_buffer + 8 * mbr * post->uv_stride, source->uv_stride,
   379                 post->uv_stride, source->uv_width, uvlimits, 8);
   380             vp8_post_proc_down_and_across_mb_row(
   381                 source->v_buffer + 8 * mbr * source->uv_stride,
   382                 post->v_buffer + 8 * mbr * post->uv_stride, source->uv_stride,
   383                 post->uv_stride, source->uv_width, uvlimits, 8);
   384         }
   385     } else
   386     {
   387         vp8_yv12_copy_frame(source, post);
   388     }
   389 }
   391 #if !(CONFIG_TEMPORAL_DENOISING)
   392 void vp8_de_noise(VP8_COMMON                 *cm,
   393                   YV12_BUFFER_CONFIG         *source,
   394                   YV12_BUFFER_CONFIG         *post,
   395                   int                         q,
   396                   int                         low_var_thresh,
   397                   int                         flag)
   398 {
   399     double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
   400     int ppl = (int)(level + .5);
   401     int mb_rows = source->y_width >> 4;
   402     int mb_cols = source->y_height >> 4;
   403     unsigned char *limits = cm->pp_limits_buffer;;
   404     int mbr, mbc;
   405     (void) post;
   406     (void) low_var_thresh;
   407     (void) flag;
   409     vpx_memset(limits, (unsigned char)ppl, 16 * mb_cols);
   411     /* TODO: The original code don't filter the 2 outer rows and columns. */
   412     for (mbr = 0; mbr < mb_rows; mbr++)
   413     {
   414         vp8_post_proc_down_and_across_mb_row(
   415             source->y_buffer + 16 * mbr * source->y_stride,
   416             source->y_buffer + 16 * mbr * source->y_stride,
   417             source->y_stride, source->y_stride, source->y_width, limits, 16);
   419         vp8_post_proc_down_and_across_mb_row(
   420             source->u_buffer + 8 * mbr * source->uv_stride,
   421             source->u_buffer + 8 * mbr * source->uv_stride,
   422             source->uv_stride, source->uv_stride, source->uv_width, limits, 8);
   423         vp8_post_proc_down_and_across_mb_row(
   424             source->v_buffer + 8 * mbr * source->uv_stride,
   425             source->v_buffer + 8 * mbr * source->uv_stride,
   426             source->uv_stride, source->uv_stride, source->uv_width, limits, 8);
   427     }
   428 }
   429 #endif
   431 double vp8_gaussian(double sigma, double mu, double x)
   432 {
   433     return 1 / (sigma * sqrt(2.0 * 3.14159265)) *
   434            (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma)));
   435 }
   437 static void fillrd(struct postproc_state *state, int q, int a)
   438 {
   439     char char_dist[300];
   441     double sigma;
   442     int i;
   444     vp8_clear_system_state();
   447     sigma = a + .5 + .6 * (63 - q) / 63.0;
   449     /* set up a lookup table of 256 entries that matches
   450      * a gaussian distribution with sigma determined by q.
   451      */
   452     {
   453         int next, j;
   455         next = 0;
   457         for (i = -32; i < 32; i++)
   458         {
   459             const int v = (int)(.5 + 256 * vp8_gaussian(sigma, 0, i));
   461             if (v)
   462             {
   463                 for (j = 0; j < v; j++)
   464                 {
   465                     char_dist[next+j] = (char) i;
   466                 }
   468                 next = next + j;
   469             }
   471         }
   473         for (; next < 256; next++)
   474             char_dist[next] = 0;
   476     }
   478     for (i = 0; i < 3072; i++)
   479     {
   480         state->noise[i] = char_dist[rand() & 0xff];
   481     }
   483     for (i = 0; i < 16; i++)
   484     {
   485         state->blackclamp[i] = -char_dist[0];
   486         state->whiteclamp[i] = -char_dist[0];
   487         state->bothclamp[i] = -2 * char_dist[0];
   488     }
   490     state->last_q = q;
   491     state->last_noise = a;
   492 }
   494 /****************************************************************************
   495  *
   496  *  ROUTINE       : plane_add_noise_c
   497  *
   498  *  INPUTS        : unsigned char *Start    starting address of buffer to add gaussian
   499  *                                  noise to
   500  *                  unsigned int Width    width of plane
   501  *                  unsigned int Height   height of plane
   502  *                  int  Pitch    distance between subsequent lines of frame
   503  *                  int  q        quantizer used to determine amount of noise
   504  *                                  to add
   505  *
   506  *  OUTPUTS       : None.
   507  *
   508  *  RETURNS       : void.
   509  *
   510  *  FUNCTION      : adds gaussian noise to a plane of pixels
   511  *
   512  *  SPECIAL NOTES : None.
   513  *
   514  ****************************************************************************/
   515 void vp8_plane_add_noise_c(unsigned char *Start, char *noise,
   516                            char blackclamp[16],
   517                            char whiteclamp[16],
   518                            char bothclamp[16],
   519                            unsigned int Width, unsigned int Height, int Pitch)
   520 {
   521     unsigned int i, j;
   523     for (i = 0; i < Height; i++)
   524     {
   525         unsigned char *Pos = Start + i * Pitch;
   526         char  *Ref = (char *)(noise + (rand() & 0xff));
   528         for (j = 0; j < Width; j++)
   529         {
   530             if (Pos[j] < blackclamp[0])
   531                 Pos[j] = blackclamp[0];
   533             if (Pos[j] > 255 + whiteclamp[0])
   534                 Pos[j] = 255 + whiteclamp[0];
   536             Pos[j] += Ref[j];
   537         }
   538     }
   539 }
   541 /* Blend the macro block with a solid colored square.  Leave the
   542  * edges unblended to give distinction to macro blocks in areas
   543  * filled with the same color block.
   544  */
   545 void vp8_blend_mb_inner_c (unsigned char *y, unsigned char *u, unsigned char *v,
   546                         int y_1, int u_1, int v_1, int alpha, int stride)
   547 {
   548     int i, j;
   549     int y1_const = y_1*((1<<16)-alpha);
   550     int u1_const = u_1*((1<<16)-alpha);
   551     int v1_const = v_1*((1<<16)-alpha);
   553     y += 2*stride + 2;
   554     for (i = 0; i < 12; i++)
   555     {
   556         for (j = 0; j < 12; j++)
   557         {
   558             y[j] = (y[j]*alpha + y1_const)>>16;
   559         }
   560         y += stride;
   561     }
   563     stride >>= 1;
   565     u += stride + 1;
   566     v += stride + 1;
   568     for (i = 0; i < 6; i++)
   569     {
   570         for (j = 0; j < 6; j++)
   571         {
   572             u[j] = (u[j]*alpha + u1_const)>>16;
   573             v[j] = (v[j]*alpha + v1_const)>>16;
   574         }
   575         u += stride;
   576         v += stride;
   577     }
   578 }
   580 /* Blend only the edge of the macro block.  Leave center
   581  * unblended to allow for other visualizations to be layered.
   582  */
   583 void vp8_blend_mb_outer_c (unsigned char *y, unsigned char *u, unsigned char *v,
   584                         int y_1, int u_1, int v_1, int alpha, int stride)
   585 {
   586     int i, j;
   587     int y1_const = y_1*((1<<16)-alpha);
   588     int u1_const = u_1*((1<<16)-alpha);
   589     int v1_const = v_1*((1<<16)-alpha);
   591     for (i = 0; i < 2; i++)
   592     {
   593         for (j = 0; j < 16; j++)
   594         {
   595             y[j] = (y[j]*alpha + y1_const)>>16;
   596         }
   597         y += stride;
   598     }
   600     for (i = 0; i < 12; i++)
   601     {
   602         y[0]  = (y[0]*alpha  + y1_const)>>16;
   603         y[1]  = (y[1]*alpha  + y1_const)>>16;
   604         y[14] = (y[14]*alpha + y1_const)>>16;
   605         y[15] = (y[15]*alpha + y1_const)>>16;
   606         y += stride;
   607     }
   609     for (i = 0; i < 2; i++)
   610     {
   611         for (j = 0; j < 16; j++)
   612         {
   613             y[j] = (y[j]*alpha + y1_const)>>16;
   614         }
   615         y += stride;
   616     }
   618     stride >>= 1;
   620     for (j = 0; j < 8; 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;
   628     for (i = 0; i < 6; i++)
   629     {
   630         u[0] = (u[0]*alpha + u1_const)>>16;
   631         v[0] = (v[0]*alpha + v1_const)>>16;
   633         u[7] = (u[7]*alpha + u1_const)>>16;
   634         v[7] = (v[7]*alpha + v1_const)>>16;
   636         u += stride;
   637         v += stride;
   638     }
   640     for (j = 0; j < 8; j++)
   641     {
   642         u[j] = (u[j]*alpha + u1_const)>>16;
   643         v[j] = (v[j]*alpha + v1_const)>>16;
   644     }
   645 }
   647 void vp8_blend_b_c (unsigned char *y, unsigned char *u, unsigned char *v,
   648                         int y_1, int u_1, int v_1, int alpha, int stride)
   649 {
   650     int i, j;
   651     int y1_const = y_1*((1<<16)-alpha);
   652     int u1_const = u_1*((1<<16)-alpha);
   653     int v1_const = v_1*((1<<16)-alpha);
   655     for (i = 0; i < 4; i++)
   656     {
   657         for (j = 0; j < 4; j++)
   658         {
   659             y[j] = (y[j]*alpha + y1_const)>>16;
   660         }
   661         y += stride;
   662     }
   664     stride >>= 1;
   666     for (i = 0; i < 2; i++)
   667     {
   668         for (j = 0; j < 2; j++)
   669         {
   670             u[j] = (u[j]*alpha + u1_const)>>16;
   671             v[j] = (v[j]*alpha + v1_const)>>16;
   672         }
   673         u += stride;
   674         v += stride;
   675     }
   676 }
   678 static void constrain_line (int x_0, int *x_1, int y_0, int *y_1, int width, int height)
   679 {
   680     int dx;
   681     int dy;
   683     if (*x_1 > width)
   684     {
   685         dx = *x_1 - x_0;
   686         dy = *y_1 - y_0;
   688         *x_1 = width;
   689         if (dx)
   690             *y_1 = ((width-x_0)*dy)/dx + y_0;
   691     }
   692     if (*x_1 < 0)
   693     {
   694         dx = *x_1 - x_0;
   695         dy = *y_1 - y_0;
   697         *x_1 = 0;
   698         if (dx)
   699             *y_1 = ((0-x_0)*dy)/dx + y_0;
   700     }
   701     if (*y_1 > height)
   702     {
   703         dx = *x_1 - x_0;
   704         dy = *y_1 - y_0;
   706         *y_1 = height;
   707         if (dy)
   708             *x_1 = ((height-y_0)*dx)/dy + x_0;
   709     }
   710     if (*y_1 < 0)
   711     {
   712         dx = *x_1 - x_0;
   713         dy = *y_1 - y_0;
   715         *y_1 = 0;
   716         if (dy)
   717             *x_1 = ((0-y_0)*dx)/dy + x_0;
   718     }
   719 }
   721 #if CONFIG_POSTPROC
   722 int vp8_post_proc_frame(VP8_COMMON *oci, YV12_BUFFER_CONFIG *dest, vp8_ppflags_t *ppflags)
   723 {
   724     int q = oci->filter_level * 10 / 6;
   725     int flags = ppflags->post_proc_flag;
   726     int deblock_level = ppflags->deblocking_level;
   727     int noise_level = ppflags->noise_level;
   729     if (!oci->frame_to_show)
   730         return -1;
   732     if (q > 63)
   733         q = 63;
   735     if (!flags)
   736     {
   737         *dest = *oci->frame_to_show;
   739         /* handle problem with extending borders */
   740         dest->y_width = oci->Width;
   741         dest->y_height = oci->Height;
   742         dest->uv_height = dest->y_height / 2;
   743         oci->postproc_state.last_base_qindex = oci->base_qindex;
   744         oci->postproc_state.last_frame_valid = 1;
   745         return 0;
   746     }
   748     /* Allocate post_proc_buffer_int if needed */
   749     if ((flags & VP8D_MFQE) && !oci->post_proc_buffer_int_used)
   750     {
   751         if ((flags & VP8D_DEBLOCK) || (flags & VP8D_DEMACROBLOCK))
   752         {
   753             int width = (oci->Width + 15) & ~15;
   754             int height = (oci->Height + 15) & ~15;
   756             if (vp8_yv12_alloc_frame_buffer(&oci->post_proc_buffer_int,
   757                                             width, height, VP8BORDERINPIXELS))
   758                 vpx_internal_error(&oci->error, VPX_CODEC_MEM_ERROR,
   759                                    "Failed to allocate MFQE framebuffer");
   761             oci->post_proc_buffer_int_used = 1;
   763             /* insure that postproc is set to all 0's so that post proc
   764              * doesn't pull random data in from edge
   765              */
   766             vpx_memset((&oci->post_proc_buffer_int)->buffer_alloc,128,(&oci->post_proc_buffer)->frame_size);
   768         }
   769     }
   771     vp8_clear_system_state();
   773     if ((flags & VP8D_MFQE) &&
   774          oci->postproc_state.last_frame_valid &&
   775          oci->current_video_frame >= 2 &&
   776          oci->postproc_state.last_base_qindex < 60 &&
   777          oci->base_qindex - oci->postproc_state.last_base_qindex >= 20)
   778     {
   779         vp8_multiframe_quality_enhance(oci);
   780         if (((flags & VP8D_DEBLOCK) || (flags & VP8D_DEMACROBLOCK)) &&
   781             oci->post_proc_buffer_int_used)
   782         {
   783             vp8_yv12_copy_frame(&oci->post_proc_buffer, &oci->post_proc_buffer_int);
   784             if (flags & VP8D_DEMACROBLOCK)
   785             {
   786                 vp8_deblock(oci, &oci->post_proc_buffer_int, &oci->post_proc_buffer,
   787                                                q + (deblock_level - 5) * 10, 1, 0);
   788                 vp8_de_mblock(&oci->post_proc_buffer,
   789                               q + (deblock_level - 5) * 10);
   790             }
   791             else if (flags & VP8D_DEBLOCK)
   792             {
   793                 vp8_deblock(oci, &oci->post_proc_buffer_int, &oci->post_proc_buffer,
   794                             q, 1, 0);
   795             }
   796         }
   797         /* Move partially towards the base q of the previous frame */
   798         oci->postproc_state.last_base_qindex = (3*oci->postproc_state.last_base_qindex + oci->base_qindex)>>2;
   799     }
   800     else if (flags & VP8D_DEMACROBLOCK)
   801     {
   802         vp8_deblock(oci, oci->frame_to_show, &oci->post_proc_buffer,
   803                                      q + (deblock_level - 5) * 10, 1, 0);
   804         vp8_de_mblock(&oci->post_proc_buffer, q + (deblock_level - 5) * 10);
   806         oci->postproc_state.last_base_qindex = oci->base_qindex;
   807     }
   808     else if (flags & VP8D_DEBLOCK)
   809     {
   810         vp8_deblock(oci, oci->frame_to_show, &oci->post_proc_buffer,
   811                     q, 1, 0);
   812         oci->postproc_state.last_base_qindex = oci->base_qindex;
   813     }
   814     else
   815     {
   816         vp8_yv12_copy_frame(oci->frame_to_show, &oci->post_proc_buffer);
   817         oci->postproc_state.last_base_qindex = oci->base_qindex;
   818     }
   819     oci->postproc_state.last_frame_valid = 1;
   821     if (flags & VP8D_ADDNOISE)
   822     {
   823         if (oci->postproc_state.last_q != q
   824             || oci->postproc_state.last_noise != noise_level)
   825         {
   826             fillrd(&oci->postproc_state, 63 - q, noise_level);
   827         }
   829         vp8_plane_add_noise
   830         (oci->post_proc_buffer.y_buffer,
   831          oci->postproc_state.noise,
   832          oci->postproc_state.blackclamp,
   833          oci->postproc_state.whiteclamp,
   834          oci->postproc_state.bothclamp,
   835          oci->post_proc_buffer.y_width, oci->post_proc_buffer.y_height,
   836          oci->post_proc_buffer.y_stride);
   837     }
   839 #if CONFIG_POSTPROC_VISUALIZER
   840     if (flags & VP8D_DEBUG_TXT_FRAME_INFO)
   841     {
   842         char message[512];
   843         sprintf(message, "F%1dG%1dQ%3dF%3dP%d_s%dx%d",
   844                 (oci->frame_type == KEY_FRAME),
   845                 oci->refresh_golden_frame,
   846                 oci->base_qindex,
   847                 oci->filter_level,
   848                 flags,
   849                 oci->mb_cols, oci->mb_rows);
   850         vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
   851     }
   853     if (flags & VP8D_DEBUG_TXT_MBLK_MODES)
   854     {
   855         int i, j;
   856         unsigned char *y_ptr;
   857         YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
   858         int mb_rows = post->y_height >> 4;
   859         int mb_cols = post->y_width  >> 4;
   860         int mb_index = 0;
   861         MODE_INFO *mi = oci->mi;
   863         y_ptr = post->y_buffer + 4 * post->y_stride + 4;
   865         /* vp8_filter each macro block */
   866         for (i = 0; i < mb_rows; i++)
   867         {
   868             for (j = 0; j < mb_cols; j++)
   869             {
   870                 char zz[4];
   872                 sprintf(zz, "%c", mi[mb_index].mbmi.mode + 'a');
   874                 vp8_blit_text(zz, y_ptr, post->y_stride);
   875                 mb_index ++;
   876                 y_ptr += 16;
   877             }
   879             mb_index ++; /* border */
   880             y_ptr += post->y_stride  * 16 - post->y_width;
   882         }
   883     }
   885     if (flags & VP8D_DEBUG_TXT_DC_DIFF)
   886     {
   887         int i, j;
   888         unsigned char *y_ptr;
   889         YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
   890         int mb_rows = post->y_height >> 4;
   891         int mb_cols = post->y_width  >> 4;
   892         int mb_index = 0;
   893         MODE_INFO *mi = oci->mi;
   895         y_ptr = post->y_buffer + 4 * post->y_stride + 4;
   897         /* vp8_filter each macro block */
   898         for (i = 0; i < mb_rows; i++)
   899         {
   900             for (j = 0; j < mb_cols; j++)
   901             {
   902                 char zz[4];
   903                 int dc_diff = !(mi[mb_index].mbmi.mode != B_PRED &&
   904                               mi[mb_index].mbmi.mode != SPLITMV &&
   905                               mi[mb_index].mbmi.mb_skip_coeff);
   907                 if (oci->frame_type == KEY_FRAME)
   908                     sprintf(zz, "a");
   909                 else
   910                     sprintf(zz, "%c", dc_diff + '0');
   912                 vp8_blit_text(zz, y_ptr, post->y_stride);
   913                 mb_index ++;
   914                 y_ptr += 16;
   915             }
   917             mb_index ++; /* border */
   918             y_ptr += post->y_stride  * 16 - post->y_width;
   920         }
   921     }
   923     if (flags & VP8D_DEBUG_TXT_RATE_INFO)
   924     {
   925         char message[512];
   926         sprintf(message, "Bitrate: %10.2f framerate: %10.2f ", oci->bitrate, oci->framerate);
   927         vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
   928     }
   930     /* Draw motion vectors */
   931     if ((flags & VP8D_DEBUG_DRAW_MV) && ppflags->display_mv_flag)
   932     {
   933         YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
   934         int width  = post->y_width;
   935         int height = post->y_height;
   936         unsigned char *y_buffer = oci->post_proc_buffer.y_buffer;
   937         int y_stride = oci->post_proc_buffer.y_stride;
   938         MODE_INFO *mi = oci->mi;
   939         int x0, y0;
   941         for (y0 = 0; y0 < height; y0 += 16)
   942         {
   943             for (x0 = 0; x0 < width; x0 += 16)
   944             {
   945                 int x1, y1;
   947                 if (!(ppflags->display_mv_flag & (1<<mi->mbmi.mode)))
   948                 {
   949                     mi++;
   950                     continue;
   951                 }
   953                 if (mi->mbmi.mode == SPLITMV)
   954                 {
   955                     switch (mi->mbmi.partitioning)
   956                     {
   957                         case 0 :    /* mv_top_bottom */
   958                         {
   959                             union b_mode_info *bmi = &mi->bmi[0];
   960                             MV *mv = &bmi->mv.as_mv;
   962                             x1 = x0 + 8 + (mv->col >> 3);
   963                             y1 = y0 + 4 + (mv->row >> 3);
   965                             constrain_line (x0+8, &x1, y0+4, &y1, width, height);
   966                             vp8_blit_line  (x0+8,  x1, y0+4,  y1, y_buffer, y_stride);
   968                             bmi = &mi->bmi[8];
   970                             x1 = x0 + 8 + (mv->col >> 3);
   971                             y1 = y0 +12 + (mv->row >> 3);
   973                             constrain_line (x0+8, &x1, y0+12, &y1, width, height);
   974                             vp8_blit_line  (x0+8,  x1, y0+12,  y1, y_buffer, y_stride);
   976                             break;
   977                         }
   978                         case 1 :    /* mv_left_right */
   979                         {
   980                             union b_mode_info *bmi = &mi->bmi[0];
   981                             MV *mv = &bmi->mv.as_mv;
   983                             x1 = x0 + 4 + (mv->col >> 3);
   984                             y1 = y0 + 8 + (mv->row >> 3);
   986                             constrain_line (x0+4, &x1, y0+8, &y1, width, height);
   987                             vp8_blit_line  (x0+4,  x1, y0+8,  y1, y_buffer, y_stride);
   989                             bmi = &mi->bmi[2];
   991                             x1 = x0 +12 + (mv->col >> 3);
   992                             y1 = y0 + 8 + (mv->row >> 3);
   994                             constrain_line (x0+12, &x1, y0+8, &y1, width, height);
   995                             vp8_blit_line  (x0+12,  x1, y0+8,  y1, y_buffer, y_stride);
   997                             break;
   998                         }
   999                         case 2 :    /* mv_quarters   */
  1001                             union b_mode_info *bmi = &mi->bmi[0];
  1002                             MV *mv = &bmi->mv.as_mv;
  1004                             x1 = x0 + 4 + (mv->col >> 3);
  1005                             y1 = y0 + 4 + (mv->row >> 3);
  1007                             constrain_line (x0+4, &x1, y0+4, &y1, width, height);
  1008                             vp8_blit_line  (x0+4,  x1, y0+4,  y1, y_buffer, y_stride);
  1010                             bmi = &mi->bmi[2];
  1012                             x1 = x0 +12 + (mv->col >> 3);
  1013                             y1 = y0 + 4 + (mv->row >> 3);
  1015                             constrain_line (x0+12, &x1, y0+4, &y1, width, height);
  1016                             vp8_blit_line  (x0+12,  x1, y0+4,  y1, y_buffer, y_stride);
  1018                             bmi = &mi->bmi[8];
  1020                             x1 = x0 + 4 + (mv->col >> 3);
  1021                             y1 = y0 +12 + (mv->row >> 3);
  1023                             constrain_line (x0+4, &x1, y0+12, &y1, width, height);
  1024                             vp8_blit_line  (x0+4,  x1, y0+12,  y1, y_buffer, y_stride);
  1026                             bmi = &mi->bmi[10];
  1028                             x1 = x0 +12 + (mv->col >> 3);
  1029                             y1 = y0 +12 + (mv->row >> 3);
  1031                             constrain_line (x0+12, &x1, y0+12, &y1, width, height);
  1032                             vp8_blit_line  (x0+12,  x1, y0+12,  y1, y_buffer, y_stride);
  1033                             break;
  1035                         default :
  1037                             union b_mode_info *bmi = mi->bmi;
  1038                             int bx0, by0;
  1040                             for (by0 = y0; by0 < (y0+16); by0 += 4)
  1042                                 for (bx0 = x0; bx0 < (x0+16); bx0 += 4)
  1044                                     MV *mv = &bmi->mv.as_mv;
  1046                                     x1 = bx0 + 2 + (mv->col >> 3);
  1047                                     y1 = by0 + 2 + (mv->row >> 3);
  1049                                     constrain_line (bx0+2, &x1, by0+2, &y1, width, height);
  1050                                     vp8_blit_line  (bx0+2,  x1, by0+2,  y1, y_buffer, y_stride);
  1052                                     bmi++;
  1058                 else if (mi->mbmi.mode >= NEARESTMV)
  1060                     MV *mv = &mi->mbmi.mv.as_mv;
  1061                     const int lx0 = x0 + 8;
  1062                     const int ly0 = y0 + 8;
  1064                     x1 = lx0 + (mv->col >> 3);
  1065                     y1 = ly0 + (mv->row >> 3);
  1067                     if (x1 != lx0 && y1 != ly0)
  1069                         constrain_line (lx0, &x1, ly0-1, &y1, width, height);
  1070                         vp8_blit_line  (lx0,  x1, ly0-1,  y1, y_buffer, y_stride);
  1072                         constrain_line (lx0, &x1, ly0+1, &y1, width, height);
  1073                         vp8_blit_line  (lx0,  x1, ly0+1,  y1, y_buffer, y_stride);
  1075                     else
  1076                         vp8_blit_line  (lx0,  x1, ly0,  y1, y_buffer, y_stride);
  1079                 mi++;
  1081             mi++;
  1085     /* Color in block modes */
  1086     if ((flags & VP8D_DEBUG_CLR_BLK_MODES)
  1087         && (ppflags->display_mb_modes_flag || ppflags->display_b_modes_flag))
  1089         int y, x;
  1090         YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
  1091         int width  = post->y_width;
  1092         int height = post->y_height;
  1093         unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
  1094         unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
  1095         unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
  1096         int y_stride = oci->post_proc_buffer.y_stride;
  1097         MODE_INFO *mi = oci->mi;
  1099         for (y = 0; y < height; y += 16)
  1101             for (x = 0; x < width; x += 16)
  1103                 int Y = 0, U = 0, V = 0;
  1105                 if (mi->mbmi.mode == B_PRED &&
  1106                     ((ppflags->display_mb_modes_flag & B_PRED) || ppflags->display_b_modes_flag))
  1108                     int by, bx;
  1109                     unsigned char *yl, *ul, *vl;
  1110                     union b_mode_info *bmi = mi->bmi;
  1112                     yl = y_ptr + x;
  1113                     ul = u_ptr + (x>>1);
  1114                     vl = v_ptr + (x>>1);
  1116                     for (by = 0; by < 16; by += 4)
  1118                         for (bx = 0; bx < 16; bx += 4)
  1120                             if ((ppflags->display_b_modes_flag & (1<<mi->mbmi.mode))
  1121                                 || (ppflags->display_mb_modes_flag & B_PRED))
  1123                                 Y = B_PREDICTION_MODE_colors[bmi->as_mode][0];
  1124                                 U = B_PREDICTION_MODE_colors[bmi->as_mode][1];
  1125                                 V = B_PREDICTION_MODE_colors[bmi->as_mode][2];
  1127                                 vp8_blend_b
  1128                                     (yl+bx, ul+(bx>>1), vl+(bx>>1), Y, U, V, 0xc000, y_stride);
  1130                             bmi++;
  1133                         yl += y_stride*4;
  1134                         ul += y_stride*1;
  1135                         vl += y_stride*1;
  1138                 else if (ppflags->display_mb_modes_flag & (1<<mi->mbmi.mode))
  1140                     Y = MB_PREDICTION_MODE_colors[mi->mbmi.mode][0];
  1141                     U = MB_PREDICTION_MODE_colors[mi->mbmi.mode][1];
  1142                     V = MB_PREDICTION_MODE_colors[mi->mbmi.mode][2];
  1144                     vp8_blend_mb_inner
  1145                         (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
  1148                 mi++;
  1150             y_ptr += y_stride*16;
  1151             u_ptr += y_stride*4;
  1152             v_ptr += y_stride*4;
  1154             mi++;
  1158     /* Color in frame reference blocks */
  1159     if ((flags & VP8D_DEBUG_CLR_FRM_REF_BLKS) && ppflags->display_ref_frame_flag)
  1161         int y, x;
  1162         YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
  1163         int width  = post->y_width;
  1164         int height = post->y_height;
  1165         unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
  1166         unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
  1167         unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
  1168         int y_stride = oci->post_proc_buffer.y_stride;
  1169         MODE_INFO *mi = oci->mi;
  1171         for (y = 0; y < height; y += 16)
  1173             for (x = 0; x < width; x +=16)
  1175                 int Y = 0, U = 0, V = 0;
  1177                 if (ppflags->display_ref_frame_flag & (1<<mi->mbmi.ref_frame))
  1179                     Y = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][0];
  1180                     U = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][1];
  1181                     V = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][2];
  1183                     vp8_blend_mb_outer
  1184                         (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
  1187                 mi++;
  1189             y_ptr += y_stride*16;
  1190             u_ptr += y_stride*4;
  1191             v_ptr += y_stride*4;
  1193             mi++;
  1196 #endif
  1198     *dest = oci->post_proc_buffer;
  1200     /* handle problem with extending borders */
  1201     dest->y_width = oci->Width;
  1202     dest->y_height = oci->Height;
  1203     dest->uv_height = dest->y_height / 2;
  1204     return 0;
  1206 #endif

mercurial