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_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"
20
21#include <limits.h>
22#include <math.h>
23#include <stdlib.h>
24#include <stdio.h>
25
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)
30
31/* global constants */
32#if CONFIG_POSTPROC_VISUALIZER
33static 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};
46
47static 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};
64
65static 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
73
74static const short kernel5[] =
75{
76    1, 1, 4, 1, 1
77};
78
79const 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};
126
127extern void vp8_blit_text(const char *msg, unsigned char *address, const int pitch);
128extern void vp8_blit_line(int x0, int x1, int y0, int y1, unsigned char *image, const int pitch);
129/***********************************************************************************************************
130 */
131void 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];
147
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;
153
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];
160
161            v = p_src[col];
162
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            }
172
173            p_dst[col] = v;
174        }
175
176        /* now post_proc_across */
177        p_src = dst_ptr;
178        p_dst = dst_ptr;
179
180        p_src[-2] = p_src[-1] = p_src[0];
181        p_src[cols] = p_src[cols + 1] = p_src[cols - 1];
182
183        for (col = 0; col < cols; col++)
184        {
185            v = p_src[col];
186
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            }
198
199            d[col & 3] = v;
200
201            if (col >= 2)
202                p_dst[col - 2] = d[(col - 2) & 3];
203        }
204
205        /* handle the last two pixels */
206        p_dst[col - 2] = d[(col - 2) & 3];
207        p_dst[col - 1] = d[(col - 1) & 3];
208
209        /* next row */
210        src_ptr += src_pixels_per_line;
211        dst_ptr += dst_pixels_per_line;
212    }
213}
214
215static int q2mbl(int x)
216{
217    if (x < 20) x = 20;
218
219    x = 50 + (x - 50) * 10 / 8;
220    return x * x / 3;
221}
222void vp8_mbpost_proc_across_ip_c(unsigned char *src, int pitch, int rows, int cols, int flimit)
223{
224    int r, c, i;
225
226    unsigned char *s = src;
227    unsigned char d[16];
228
229    for (r = 0; r < rows; r++)
230    {
231        int sumsq = 0;
232        int sum   = 0;
233
234        for (i = -8; i<0; i++)
235          s[i]=s[0];
236
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];
242
243        for (i = -8; i <= 6; i++)
244        {
245            sumsq += s[i] * s[i];
246            sum   += s[i];
247            d[i+8] = 0;
248        }
249
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];
254
255            sum  += x;
256            sumsq += x * y;
257
258            d[c&15] = s[c];
259
260            if (sumsq * 15 - sum * sum < flimit)
261            {
262                d[c&15] = (8 + sum + s[c]) >> 4;
263            }
264
265            s[c-8] = d[(c-8)&15];
266        }
267
268        s += pitch;
269    }
270}
271
272
273void 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()];
277
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);
285
286        for (i = -8; i < 0; i++)
287          s[i*pitch]=s[0];
288
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];
294
295        for (i = -8; i <= 6; i++)
296        {
297            sumsq += s[i*pitch] * s[i*pitch];
298            sum   += s[i*pitch];
299        }
300
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];
306
307            if (sumsq * 15 - sum * sum < flimit)
308            {
309                d[r&15] = (rv2[r&127] + sum + s[0]) >> 4;
310            }
311
312            s[-8*pitch] = d[(r-8)&15];
313            s += pitch;
314        }
315    }
316}
317
318static 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}
326
327void 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);
336
337    const MODE_INFO *mode_info_context = cm->show_frame_mi;
338    int mbr, mbc;
339
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;
346
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;
356
357                if (mode_info_context->mbmi.mb_skip_coeff)
358                    mb_ppl = (unsigned char)ppl >> 1;
359                else
360                    mb_ppl = (unsigned char)ppl;
361
362                vpx_memset(ylptr, mb_ppl, 16);
363                vpx_memset(uvlptr, mb_ppl, 8);
364
365                ylptr += 16;
366                uvlptr += 8;
367                mode_info_context++;
368            }
369            mode_info_context++;
370
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);
375
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}
390
391#if !(CONFIG_TEMPORAL_DENOISING)
392void 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;
408
409    vpx_memset(limits, (unsigned char)ppl, 16 * mb_cols);
410
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);
418
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
430
431double 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}
436
437static void fillrd(struct postproc_state *state, int q, int a)
438{
439    char char_dist[300];
440
441    double sigma;
442    int i;
443
444    vp8_clear_system_state();
445
446
447    sigma = a + .5 + .6 * (63 - q) / 63.0;
448
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;
454
455        next = 0;
456
457        for (i = -32; i < 32; i++)
458        {
459            const int v = (int)(.5 + 256 * vp8_gaussian(sigma, 0, i));
460
461            if (v)
462            {
463                for (j = 0; j < v; j++)
464                {
465                    char_dist[next+j] = (char) i;
466                }
467
468                next = next + j;
469            }
470
471        }
472
473        for (; next < 256; next++)
474            char_dist[next] = 0;
475
476    }
477
478    for (i = 0; i < 3072; i++)
479    {
480        state->noise[i] = char_dist[rand() & 0xff];
481    }
482
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    }
489
490    state->last_q = q;
491    state->last_noise = a;
492}
493
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 ****************************************************************************/
515void 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;
522
523    for (i = 0; i < Height; i++)
524    {
525        unsigned char *Pos = Start + i * Pitch;
526        char  *Ref = (char *)(noise + (rand() & 0xff));
527
528        for (j = 0; j < Width; j++)
529        {
530            if (Pos[j] < blackclamp[0])
531                Pos[j] = blackclamp[0];
532
533            if (Pos[j] > 255 + whiteclamp[0])
534                Pos[j] = 255 + whiteclamp[0];
535
536            Pos[j] += Ref[j];
537        }
538    }
539}
540
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 */
545void 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);
552
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    }
562
563    stride >>= 1;
564
565    u += stride + 1;
566    v += stride + 1;
567
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}
579
580/* Blend only the edge of the macro block.  Leave center
581 * unblended to allow for other visualizations to be layered.
582 */
583void 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);
590
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    }
599
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    }
608
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    }
617
618    stride >>= 1;
619
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;
627
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;
632
633        u[7] = (u[7]*alpha + u1_const)>>16;
634        v[7] = (v[7]*alpha + v1_const)>>16;
635
636        u += stride;
637        v += stride;
638    }
639
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}
646
647void 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);
654
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    }
663
664    stride >>= 1;
665
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}
677
678static 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;
682
683    if (*x_1 > width)
684    {
685        dx = *x_1 - x_0;
686        dy = *y_1 - y_0;
687
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;
696
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;
705
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;
714
715        *y_1 = 0;
716        if (dy)
717            *x_1 = ((0-y_0)*dx)/dy + x_0;
718    }
719}
720
721#if CONFIG_POSTPROC
722int 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;
728
729    if (!oci->frame_to_show)
730        return -1;
731
732    if (q > 63)
733        q = 63;
734
735    if (!flags)
736    {
737        *dest = *oci->frame_to_show;
738
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    }
747
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;
755
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");
760
761            oci->post_proc_buffer_int_used = 1;
762
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);
767
768        }
769    }
770
771    vp8_clear_system_state();
772
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);
805
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;
820
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        }
828
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    }
838
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    }
852
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;
862
863        y_ptr = post->y_buffer + 4 * post->y_stride + 4;
864
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];
871
872                sprintf(zz, "%c", mi[mb_index].mbmi.mode + 'a');
873
874                vp8_blit_text(zz, y_ptr, post->y_stride);
875                mb_index ++;
876                y_ptr += 16;
877            }
878
879            mb_index ++; /* border */
880            y_ptr += post->y_stride  * 16 - post->y_width;
881
882        }
883    }
884
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;
894
895        y_ptr = post->y_buffer + 4 * post->y_stride + 4;
896
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);
906
907                if (oci->frame_type == KEY_FRAME)
908                    sprintf(zz, "a");
909                else
910                    sprintf(zz, "%c", dc_diff + '0');
911
912                vp8_blit_text(zz, y_ptr, post->y_stride);
913                mb_index ++;
914                y_ptr += 16;
915            }
916
917            mb_index ++; /* border */
918            y_ptr += post->y_stride  * 16 - post->y_width;
919
920        }
921    }
922
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    }
929
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;
940
941        for (y0 = 0; y0 < height; y0 += 16)
942        {
943            for (x0 = 0; x0 < width; x0 += 16)
944            {
945                int x1, y1;
946
947                if (!(ppflags->display_mv_flag & (1<<mi->mbmi.mode)))
948                {
949                    mi++;
950                    continue;
951                }
952
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;
961
962                            x1 = x0 + 8 + (mv->col >> 3);
963                            y1 = y0 + 4 + (mv->row >> 3);
964
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);
967
968                            bmi = &mi->bmi[8];
969
970                            x1 = x0 + 8 + (mv->col >> 3);
971                            y1 = y0 +12 + (mv->row >> 3);
972
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);
975
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;
982
983                            x1 = x0 + 4 + (mv->col >> 3);
984                            y1 = y0 + 8 + (mv->row >> 3);
985
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);
988
989                            bmi = &mi->bmi[2];
990
991                            x1 = x0 +12 + (mv->col >> 3);
992                            y1 = y0 + 8 + (mv->row >> 3);
993
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);
996
997                            break;
998                        }
999                        case 2 :    /* mv_quarters   */
1000                        {
1001                            union b_mode_info *bmi = &mi->bmi[0];
1002                            MV *mv = &bmi->mv.as_mv;
1003
1004                            x1 = x0 + 4 + (mv->col >> 3);
1005                            y1 = y0 + 4 + (mv->row >> 3);
1006
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);
1009
1010                            bmi = &mi->bmi[2];
1011
1012                            x1 = x0 +12 + (mv->col >> 3);
1013                            y1 = y0 + 4 + (mv->row >> 3);
1014
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);
1017
1018                            bmi = &mi->bmi[8];
1019
1020                            x1 = x0 + 4 + (mv->col >> 3);
1021                            y1 = y0 +12 + (mv->row >> 3);
1022
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);
1025
1026                            bmi = &mi->bmi[10];
1027
1028                            x1 = x0 +12 + (mv->col >> 3);
1029                            y1 = y0 +12 + (mv->row >> 3);
1030
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;
1034                        }
1035                        default :
1036                        {
1037                            union b_mode_info *bmi = mi->bmi;
1038                            int bx0, by0;
1039
1040                            for (by0 = y0; by0 < (y0+16); by0 += 4)
1041                            {
1042                                for (bx0 = x0; bx0 < (x0+16); bx0 += 4)
1043                                {
1044                                    MV *mv = &bmi->mv.as_mv;
1045
1046                                    x1 = bx0 + 2 + (mv->col >> 3);
1047                                    y1 = by0 + 2 + (mv->row >> 3);
1048
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);
1051
1052                                    bmi++;
1053                                }
1054                            }
1055                        }
1056                    }
1057                }
1058                else if (mi->mbmi.mode >= NEARESTMV)
1059                {
1060                    MV *mv = &mi->mbmi.mv.as_mv;
1061                    const int lx0 = x0 + 8;
1062                    const int ly0 = y0 + 8;
1063
1064                    x1 = lx0 + (mv->col >> 3);
1065                    y1 = ly0 + (mv->row >> 3);
1066
1067                    if (x1 != lx0 && y1 != ly0)
1068                    {
1069                        constrain_line (lx0, &x1, ly0-1, &y1, width, height);
1070                        vp8_blit_line  (lx0,  x1, ly0-1,  y1, y_buffer, y_stride);
1071
1072                        constrain_line (lx0, &x1, ly0+1, &y1, width, height);
1073                        vp8_blit_line  (lx0,  x1, ly0+1,  y1, y_buffer, y_stride);
1074                    }
1075                    else
1076                        vp8_blit_line  (lx0,  x1, ly0,  y1, y_buffer, y_stride);
1077                }
1078
1079                mi++;
1080            }
1081            mi++;
1082        }
1083    }
1084
1085    /* Color in block modes */
1086    if ((flags & VP8D_DEBUG_CLR_BLK_MODES)
1087        && (ppflags->display_mb_modes_flag || ppflags->display_b_modes_flag))
1088    {
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;
1098
1099        for (y = 0; y < height; y += 16)
1100        {
1101            for (x = 0; x < width; x += 16)
1102            {
1103                int Y = 0, U = 0, V = 0;
1104
1105                if (mi->mbmi.mode == B_PRED &&
1106                    ((ppflags->display_mb_modes_flag & B_PRED) || ppflags->display_b_modes_flag))
1107                {
1108                    int by, bx;
1109                    unsigned char *yl, *ul, *vl;
1110                    union b_mode_info *bmi = mi->bmi;
1111
1112                    yl = y_ptr + x;
1113                    ul = u_ptr + (x>>1);
1114                    vl = v_ptr + (x>>1);
1115
1116                    for (by = 0; by < 16; by += 4)
1117                    {
1118                        for (bx = 0; bx < 16; bx += 4)
1119                        {
1120                            if ((ppflags->display_b_modes_flag & (1<<mi->mbmi.mode))
1121                                || (ppflags->display_mb_modes_flag & B_PRED))
1122                            {
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];
1126
1127                                vp8_blend_b
1128                                    (yl+bx, ul+(bx>>1), vl+(bx>>1), Y, U, V, 0xc000, y_stride);
1129                            }
1130                            bmi++;
1131                        }
1132
1133                        yl += y_stride*4;
1134                        ul += y_stride*1;
1135                        vl += y_stride*1;
1136                    }
1137                }
1138                else if (ppflags->display_mb_modes_flag & (1<<mi->mbmi.mode))
1139                {
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];
1143
1144                    vp8_blend_mb_inner
1145                        (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1146                }
1147
1148                mi++;
1149            }
1150            y_ptr += y_stride*16;
1151            u_ptr += y_stride*4;
1152            v_ptr += y_stride*4;
1153
1154            mi++;
1155        }
1156    }
1157
1158    /* Color in frame reference blocks */
1159    if ((flags & VP8D_DEBUG_CLR_FRM_REF_BLKS) && ppflags->display_ref_frame_flag)
1160    {
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;
1170
1171        for (y = 0; y < height; y += 16)
1172        {
1173            for (x = 0; x < width; x +=16)
1174            {
1175                int Y = 0, U = 0, V = 0;
1176
1177                if (ppflags->display_ref_frame_flag & (1<<mi->mbmi.ref_frame))
1178                {
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];
1182
1183                    vp8_blend_mb_outer
1184                        (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1185                }
1186
1187                mi++;
1188            }
1189            y_ptr += y_stride*16;
1190            u_ptr += y_stride*4;
1191            v_ptr += y_stride*4;
1192
1193            mi++;
1194        }
1195    }
1196#endif
1197
1198    *dest = oci->post_proc_buffer;
1199
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;
1205}
1206#endif
1207