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