PageRenderTime 94ms CodeModel.GetById 18ms app.highlight 67ms RepoModel.GetById 2ms app.codeStats 0ms

/media/libvpx/vp8/common/postproc.c

http://github.com/zpao/v8monkey
C | 1109 lines | 865 code | 190 blank | 54 comment | 111 complexity | 7d885558b841afd56596fc6744deaa64 MD5 | raw file
   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
  30static 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
  44static 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
  62static 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
  71static const short kernel5[] =
  72{
  73    1, 1, 4, 1, 1
  74};
  75
  76const 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
 125extern void vp8_blit_text(const char *msg, unsigned char *address, const int pitch);
 126extern void vp8_blit_line(int x0, int x1, int y0, int y1, unsigned char *image, const int pitch);
 127/***********************************************************************************************************
 128 */
 129void 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
 214static 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}
 221void 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
 267void 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
 304static 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
 325void 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
 342void 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
 380double 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
 386extern void (*vp8_clear_system_state)(void);
 387
 388
 389static 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 ****************************************************************************/
 468void 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 */
 498void 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 */
 536void 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
 600void 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
 631static 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
 681int 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                int dc_diff = !(mi[mb_index].mbmi.mode != B_PRED &&
 808                              mi[mb_index].mbmi.mode != SPLITMV &&
 809                              mi[mb_index].mbmi.mb_skip_coeff);
 810
 811                if (oci->frame_type == KEY_FRAME)
 812                    sprintf(zz, "a");
 813                else
 814                    sprintf(zz, "%c", dc_diff + '0');
 815
 816                vp8_blit_text(zz, y_ptr, post->y_stride);
 817                mb_index ++;
 818                y_ptr += 16;
 819            }
 820
 821            mb_index ++; /* border */
 822            y_ptr += post->y_stride  * 16 - post->y_width;
 823
 824        }
 825    }
 826
 827    if (flags & VP8D_DEBUG_TXT_RATE_INFO)
 828    {
 829        char message[512];
 830        sprintf(message, "Bitrate: %10.2f frame_rate: %10.2f ", oci->bitrate, oci->framerate);
 831        vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
 832    }
 833
 834    /* Draw motion vectors */
 835    if ((flags & VP8D_DEBUG_DRAW_MV) && ppflags->display_mv_flag)
 836    {
 837        YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
 838        int width  = post->y_width;
 839        int height = post->y_height;
 840        unsigned char *y_buffer = oci->post_proc_buffer.y_buffer;
 841        int y_stride = oci->post_proc_buffer.y_stride;
 842        MODE_INFO *mi = oci->mi;
 843        int x0, y0;
 844
 845        for (y0 = 0; y0 < height; y0 += 16)
 846        {
 847            for (x0 = 0; x0 < width; x0 += 16)
 848            {
 849                int x1, y1;
 850
 851                if (!(ppflags->display_mv_flag & (1<<mi->mbmi.mode)))
 852                {
 853                    mi++;
 854                    continue;
 855                }
 856
 857                if (mi->mbmi.mode == SPLITMV)
 858                {
 859                    switch (mi->mbmi.partitioning)
 860                    {
 861                        case 0 :    /* mv_top_bottom */
 862                        {
 863                            union b_mode_info *bmi = &mi->bmi[0];
 864                            MV *mv = &bmi->mv.as_mv;
 865
 866                            x1 = x0 + 8 + (mv->col >> 3);
 867                            y1 = y0 + 4 + (mv->row >> 3);
 868
 869                            constrain_line (x0+8, &x1, y0+4, &y1, width, height);
 870                            vp8_blit_line  (x0+8,  x1, y0+4,  y1, y_buffer, y_stride);
 871
 872                            bmi = &mi->bmi[8];
 873
 874                            x1 = x0 + 8 + (mv->col >> 3);
 875                            y1 = y0 +12 + (mv->row >> 3);
 876
 877                            constrain_line (x0+8, &x1, y0+12, &y1, width, height);
 878                            vp8_blit_line  (x0+8,  x1, y0+12,  y1, y_buffer, y_stride);
 879
 880                            break;
 881                        }
 882                        case 1 :    /* mv_left_right */
 883                        {
 884                            union b_mode_info *bmi = &mi->bmi[0];
 885                            MV *mv = &bmi->mv.as_mv;
 886
 887                            x1 = x0 + 4 + (mv->col >> 3);
 888                            y1 = y0 + 8 + (mv->row >> 3);
 889
 890                            constrain_line (x0+4, &x1, y0+8, &y1, width, height);
 891                            vp8_blit_line  (x0+4,  x1, y0+8,  y1, y_buffer, y_stride);
 892
 893                            bmi = &mi->bmi[2];
 894
 895                            x1 = x0 +12 + (mv->col >> 3);
 896                            y1 = y0 + 8 + (mv->row >> 3);
 897
 898                            constrain_line (x0+12, &x1, y0+8, &y1, width, height);
 899                            vp8_blit_line  (x0+12,  x1, y0+8,  y1, y_buffer, y_stride);
 900
 901                            break;
 902                        }
 903                        case 2 :    /* mv_quarters   */
 904                        {
 905                            union b_mode_info *bmi = &mi->bmi[0];
 906                            MV *mv = &bmi->mv.as_mv;
 907
 908                            x1 = x0 + 4 + (mv->col >> 3);
 909                            y1 = y0 + 4 + (mv->row >> 3);
 910
 911                            constrain_line (x0+4, &x1, y0+4, &y1, width, height);
 912                            vp8_blit_line  (x0+4,  x1, y0+4,  y1, y_buffer, y_stride);
 913
 914                            bmi = &mi->bmi[2];
 915
 916                            x1 = x0 +12 + (mv->col >> 3);
 917                            y1 = y0 + 4 + (mv->row >> 3);
 918
 919                            constrain_line (x0+12, &x1, y0+4, &y1, width, height);
 920                            vp8_blit_line  (x0+12,  x1, y0+4,  y1, y_buffer, y_stride);
 921
 922                            bmi = &mi->bmi[8];
 923
 924                            x1 = x0 + 4 + (mv->col >> 3);
 925                            y1 = y0 +12 + (mv->row >> 3);
 926
 927                            constrain_line (x0+4, &x1, y0+12, &y1, width, height);
 928                            vp8_blit_line  (x0+4,  x1, y0+12,  y1, y_buffer, y_stride);
 929
 930                            bmi = &mi->bmi[10];
 931
 932                            x1 = x0 +12 + (mv->col >> 3);
 933                            y1 = y0 +12 + (mv->row >> 3);
 934
 935                            constrain_line (x0+12, &x1, y0+12, &y1, width, height);
 936                            vp8_blit_line  (x0+12,  x1, y0+12,  y1, y_buffer, y_stride);
 937                            break;
 938                        }
 939                        default :
 940                        {
 941                            union b_mode_info *bmi = mi->bmi;
 942                            int bx0, by0;
 943
 944                            for (by0 = y0; by0 < (y0+16); by0 += 4)
 945                            {
 946                                for (bx0 = x0; bx0 < (x0+16); bx0 += 4)
 947                                {
 948                                    MV *mv = &bmi->mv.as_mv;
 949
 950                                    x1 = bx0 + 2 + (mv->col >> 3);
 951                                    y1 = by0 + 2 + (mv->row >> 3);
 952
 953                                    constrain_line (bx0+2, &x1, by0+2, &y1, width, height);
 954                                    vp8_blit_line  (bx0+2,  x1, by0+2,  y1, y_buffer, y_stride);
 955
 956                                    bmi++;
 957                                }
 958                            }
 959                        }
 960                    }
 961                }
 962                else if (mi->mbmi.mode >= NEARESTMV)
 963                {
 964                    MV *mv = &mi->mbmi.mv.as_mv;
 965                    const int lx0 = x0 + 8;
 966                    const int ly0 = y0 + 8;
 967
 968                    x1 = lx0 + (mv->col >> 3);
 969                    y1 = ly0 + (mv->row >> 3);
 970
 971                    if (x1 != lx0 && y1 != ly0)
 972                    {
 973                        constrain_line (lx0, &x1, ly0-1, &y1, width, height);
 974                        vp8_blit_line  (lx0,  x1, ly0-1,  y1, y_buffer, y_stride);
 975
 976                        constrain_line (lx0, &x1, ly0+1, &y1, width, height);
 977                        vp8_blit_line  (lx0,  x1, ly0+1,  y1, y_buffer, y_stride);
 978                    }
 979                    else
 980                        vp8_blit_line  (lx0,  x1, ly0,  y1, y_buffer, y_stride);
 981                }
 982
 983                mi++;
 984            }
 985            mi++;
 986        }
 987    }
 988
 989    /* Color in block modes */
 990    if ((flags & VP8D_DEBUG_CLR_BLK_MODES)
 991        && (ppflags->display_mb_modes_flag || ppflags->display_b_modes_flag))
 992    {
 993        int y, x;
 994        YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
 995        int width  = post->y_width;
 996        int height = post->y_height;
 997        unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
 998        unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
 999        unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
1000        int y_stride = oci->post_proc_buffer.y_stride;
1001        MODE_INFO *mi = oci->mi;
1002
1003        for (y = 0; y < height; y += 16)
1004        {
1005            for (x = 0; x < width; x += 16)
1006            {
1007                int Y = 0, U = 0, V = 0;
1008
1009                if (mi->mbmi.mode == B_PRED &&
1010                    ((ppflags->display_mb_modes_flag & B_PRED) || ppflags->display_b_modes_flag))
1011                {
1012                    int by, bx;
1013                    unsigned char *yl, *ul, *vl;
1014                    union b_mode_info *bmi = mi->bmi;
1015
1016                    yl = y_ptr + x;
1017                    ul = u_ptr + (x>>1);
1018                    vl = v_ptr + (x>>1);
1019
1020                    for (by = 0; by < 16; by += 4)
1021                    {
1022                        for (bx = 0; bx < 16; bx += 4)
1023                        {
1024                            if ((ppflags->display_b_modes_flag & (1<<mi->mbmi.mode))
1025                                || (ppflags->display_mb_modes_flag & B_PRED))
1026                            {
1027                                Y = B_PREDICTION_MODE_colors[bmi->as_mode][0];
1028                                U = B_PREDICTION_MODE_colors[bmi->as_mode][1];
1029                                V = B_PREDICTION_MODE_colors[bmi->as_mode][2];
1030
1031                                POSTPROC_INVOKE(RTCD_VTABLE(oci), blend_b)
1032                                    (yl+bx, ul+(bx>>1), vl+(bx>>1), Y, U, V, 0xc000, y_stride);
1033                            }
1034                            bmi++;
1035                        }
1036
1037                        yl += y_stride*4;
1038                        ul += y_stride*1;
1039                        vl += y_stride*1;
1040                    }
1041                }
1042                else if (ppflags->display_mb_modes_flag & (1<<mi->mbmi.mode))
1043                {
1044                    Y = MB_PREDICTION_MODE_colors[mi->mbmi.mode][0];
1045                    U = MB_PREDICTION_MODE_colors[mi->mbmi.mode][1];
1046                    V = MB_PREDICTION_MODE_colors[mi->mbmi.mode][2];
1047
1048                    POSTPROC_INVOKE(RTCD_VTABLE(oci), blend_mb_inner)
1049                        (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1050                }
1051
1052                mi++;
1053            }
1054            y_ptr += y_stride*16;
1055            u_ptr += y_stride*4;
1056            v_ptr += y_stride*4;
1057
1058            mi++;
1059        }
1060    }
1061
1062    /* Color in frame reference blocks */
1063    if ((flags & VP8D_DEBUG_CLR_FRM_REF_BLKS) && ppflags->display_ref_frame_flag)
1064    {
1065        int y, x;
1066        YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
1067        int width  = post->y_width;
1068        int height = post->y_height;
1069        unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
1070        unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
1071        unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
1072        int y_stride = oci->post_proc_buffer.y_stride;
1073        MODE_INFO *mi = oci->mi;
1074
1075        for (y = 0; y < height; y += 16)
1076        {
1077            for (x = 0; x < width; x +=16)
1078            {
1079                int Y = 0, U = 0, V = 0;
1080
1081                if (ppflags->display_ref_frame_flag & (1<<mi->mbmi.ref_frame))
1082                {
1083                    Y = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][0];
1084                    U = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][1];
1085                    V = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][2];
1086
1087                    POSTPROC_INVOKE(RTCD_VTABLE(oci), blend_mb_outer)
1088                        (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1089                }
1090
1091                mi++;
1092            }
1093            y_ptr += y_stride*16;
1094            u_ptr += y_stride*4;
1095            v_ptr += y_stride*4;
1096
1097            mi++;
1098        }
1099    }
1100#endif
1101
1102    *dest = oci->post_proc_buffer;
1103
1104    /* handle problem with extending borders */
1105    dest->y_width = oci->Width;
1106    dest->y_height = oci->Height;
1107    dest->uv_height = dest->y_height / 2;
1108    return 0;
1109}