• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
vp8_post_proc_down_and_across_mb_row_c(unsigned char * src_ptr,unsigned char * dst_ptr,int src_pixels_per_line,int dst_pixels_per_line,int cols,unsigned char * f,int size)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 
q2mbl(int x)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 
vp8_mbpost_proc_across_ip_c(unsigned char * src,int pitch,int rows,int cols,int flimit)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 
vp8_mbpost_proc_down_c(unsigned char * dst,int pitch,int rows,int cols,int flimit)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
vp8_de_mblock(YV12_BUFFER_CONFIG * post,int q)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 
vp8_deblock(VP8_COMMON * cm,YV12_BUFFER_CONFIG * source,YV12_BUFFER_CONFIG * post,int q,int low_var_thresh,int flag)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 
vp8_de_noise(VP8_COMMON * cm,YV12_BUFFER_CONFIG * source,YV12_BUFFER_CONFIG * post,int q,int low_var_thresh,int flag,int uvfilter)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 
vp8_gaussian(double sigma,double mu,double x)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 
fillrd(struct postproc_state * state,int q,int a)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  ****************************************************************************/
vp8_plane_add_noise_c(unsigned char * Start,char * noise,char blackclamp[16],char whiteclamp[16],char bothclamp[16],unsigned int Width,unsigned int Height,int Pitch)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  */
vp8_blend_mb_inner_c(unsigned char * y,unsigned char * u,unsigned char * v,int y_1,int u_1,int v_1,int alpha,int stride)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  */
vp8_blend_mb_outer_c(unsigned char * y,unsigned char * u,unsigned char * v,int y_1,int u_1,int v_1,int alpha,int stride)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 
vp8_blend_b_c(unsigned char * y,unsigned char * u,unsigned char * v,int y_1,int u_1,int v_1,int alpha,int stride)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 
constrain_line(int x_0,int * x_1,int y_0,int * y_1,int width,int height)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
vp8_post_proc_frame(VP8_COMMON * oci,YV12_BUFFER_CONFIG * dest,vp8_ppflags_t * ppflags)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
1206