• 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                 memset(ylptr, mb_ppl, 16);
359                 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     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 
gaussian(double sigma,double mu,double x)430 static double 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 * 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     (void)bothclamp;
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  */
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)545 void vp8_blend_mb_inner_c (unsigned char *y, unsigned char *u, unsigned char *v,
546                         int y_1, int u_1, int v_1, int alpha, int stride)
547 {
548     int i, j;
549     int y1_const = y_1*((1<<16)-alpha);
550     int u1_const = u_1*((1<<16)-alpha);
551     int v1_const = v_1*((1<<16)-alpha);
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  */
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)583 void vp8_blend_mb_outer_c (unsigned char *y, unsigned char *u, unsigned char *v,
584                         int y_1, int u_1, int v_1, int alpha, int stride)
585 {
586     int i, j;
587     int y1_const = y_1*((1<<16)-alpha);
588     int u1_const = u_1*((1<<16)-alpha);
589     int v1_const = v_1*((1<<16)-alpha);
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 
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)647 void vp8_blend_b_c (unsigned char *y, unsigned char *u, unsigned char *v,
648                         int y_1, int u_1, int v_1, int alpha, int stride)
649 {
650     int i, j;
651     int y1_const = y_1*((1<<16)-alpha);
652     int u1_const = u_1*((1<<16)-alpha);
653     int v1_const = v_1*((1<<16)-alpha);
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 
678 #if CONFIG_POSTPROC_VISUALIZER
constrain_line(int x_0,int * x_1,int y_0,int * y_1,int width,int height)679 static void constrain_line (int x_0, int *x_1, int y_0, int *y_1, int width, int height)
680 {
681     int dx;
682     int dy;
683 
684     if (*x_1 > width)
685     {
686         dx = *x_1 - x_0;
687         dy = *y_1 - y_0;
688 
689         *x_1 = width;
690         if (dx)
691             *y_1 = ((width-x_0)*dy)/dx + y_0;
692     }
693     if (*x_1 < 0)
694     {
695         dx = *x_1 - x_0;
696         dy = *y_1 - y_0;
697 
698         *x_1 = 0;
699         if (dx)
700             *y_1 = ((0-x_0)*dy)/dx + y_0;
701     }
702     if (*y_1 > height)
703     {
704         dx = *x_1 - x_0;
705         dy = *y_1 - y_0;
706 
707         *y_1 = height;
708         if (dy)
709             *x_1 = ((height-y_0)*dx)/dy + x_0;
710     }
711     if (*y_1 < 0)
712     {
713         dx = *x_1 - x_0;
714         dy = *y_1 - y_0;
715 
716         *y_1 = 0;
717         if (dy)
718             *x_1 = ((0-y_0)*dx)/dy + x_0;
719     }
720 }
721 #endif  // CONFIG_POSTPROC_VISUALIZER
722 
723 #if CONFIG_POSTPROC
vp8_post_proc_frame(VP8_COMMON * oci,YV12_BUFFER_CONFIG * dest,vp8_ppflags_t * ppflags)724 int vp8_post_proc_frame(VP8_COMMON *oci, YV12_BUFFER_CONFIG *dest, vp8_ppflags_t *ppflags)
725 {
726     int q = oci->filter_level * 10 / 6;
727     int flags = ppflags->post_proc_flag;
728     int deblock_level = ppflags->deblocking_level;
729     int noise_level = ppflags->noise_level;
730 
731     if (!oci->frame_to_show)
732         return -1;
733 
734     if (q > 63)
735         q = 63;
736 
737     if (!flags)
738     {
739         *dest = *oci->frame_to_show;
740 
741         /* handle problem with extending borders */
742         dest->y_width = oci->Width;
743         dest->y_height = oci->Height;
744         dest->uv_height = dest->y_height / 2;
745         oci->postproc_state.last_base_qindex = oci->base_qindex;
746         oci->postproc_state.last_frame_valid = 1;
747         return 0;
748     }
749 
750     /* Allocate post_proc_buffer_int if needed */
751     if ((flags & VP8D_MFQE) && !oci->post_proc_buffer_int_used)
752     {
753         if ((flags & VP8D_DEBLOCK) || (flags & VP8D_DEMACROBLOCK))
754         {
755             int width = (oci->Width + 15) & ~15;
756             int height = (oci->Height + 15) & ~15;
757 
758             if (vp8_yv12_alloc_frame_buffer(&oci->post_proc_buffer_int,
759                                             width, height, VP8BORDERINPIXELS))
760                 vpx_internal_error(&oci->error, VPX_CODEC_MEM_ERROR,
761                                    "Failed to allocate MFQE framebuffer");
762 
763             oci->post_proc_buffer_int_used = 1;
764 
765             /* insure that postproc is set to all 0's so that post proc
766              * doesn't pull random data in from edge
767              */
768             memset((&oci->post_proc_buffer_int)->buffer_alloc,128,(&oci->post_proc_buffer)->frame_size);
769 
770         }
771     }
772 
773     vp8_clear_system_state();
774 
775     if ((flags & VP8D_MFQE) &&
776          oci->postproc_state.last_frame_valid &&
777          oci->current_video_frame >= 2 &&
778          oci->postproc_state.last_base_qindex < 60 &&
779          oci->base_qindex - oci->postproc_state.last_base_qindex >= 20)
780     {
781         vp8_multiframe_quality_enhance(oci);
782         if (((flags & VP8D_DEBLOCK) || (flags & VP8D_DEMACROBLOCK)) &&
783             oci->post_proc_buffer_int_used)
784         {
785             vp8_yv12_copy_frame(&oci->post_proc_buffer, &oci->post_proc_buffer_int);
786             if (flags & VP8D_DEMACROBLOCK)
787             {
788                 vp8_deblock(oci, &oci->post_proc_buffer_int, &oci->post_proc_buffer,
789                                                q + (deblock_level - 5) * 10, 1, 0);
790                 vp8_de_mblock(&oci->post_proc_buffer,
791                               q + (deblock_level - 5) * 10);
792             }
793             else if (flags & VP8D_DEBLOCK)
794             {
795                 vp8_deblock(oci, &oci->post_proc_buffer_int, &oci->post_proc_buffer,
796                             q, 1, 0);
797             }
798         }
799         /* Move partially towards the base q of the previous frame */
800         oci->postproc_state.last_base_qindex = (3*oci->postproc_state.last_base_qindex + oci->base_qindex)>>2;
801     }
802     else if (flags & VP8D_DEMACROBLOCK)
803     {
804         vp8_deblock(oci, oci->frame_to_show, &oci->post_proc_buffer,
805                                      q + (deblock_level - 5) * 10, 1, 0);
806         vp8_de_mblock(&oci->post_proc_buffer, q + (deblock_level - 5) * 10);
807 
808         oci->postproc_state.last_base_qindex = oci->base_qindex;
809     }
810     else if (flags & VP8D_DEBLOCK)
811     {
812         vp8_deblock(oci, oci->frame_to_show, &oci->post_proc_buffer,
813                     q, 1, 0);
814         oci->postproc_state.last_base_qindex = oci->base_qindex;
815     }
816     else
817     {
818         vp8_yv12_copy_frame(oci->frame_to_show, &oci->post_proc_buffer);
819         oci->postproc_state.last_base_qindex = oci->base_qindex;
820     }
821     oci->postproc_state.last_frame_valid = 1;
822 
823     if (flags & VP8D_ADDNOISE)
824     {
825         if (oci->postproc_state.last_q != q
826             || oci->postproc_state.last_noise != noise_level)
827         {
828             fillrd(&oci->postproc_state, 63 - q, noise_level);
829         }
830 
831         vp8_plane_add_noise
832         (oci->post_proc_buffer.y_buffer,
833          oci->postproc_state.noise,
834          oci->postproc_state.blackclamp,
835          oci->postproc_state.whiteclamp,
836          oci->postproc_state.bothclamp,
837          oci->post_proc_buffer.y_width, oci->post_proc_buffer.y_height,
838          oci->post_proc_buffer.y_stride);
839     }
840 
841 #if CONFIG_POSTPROC_VISUALIZER
842     if (flags & VP8D_DEBUG_TXT_FRAME_INFO)
843     {
844         char message[512];
845         sprintf(message, "F%1dG%1dQ%3dF%3dP%d_s%dx%d",
846                 (oci->frame_type == KEY_FRAME),
847                 oci->refresh_golden_frame,
848                 oci->base_qindex,
849                 oci->filter_level,
850                 flags,
851                 oci->mb_cols, oci->mb_rows);
852         vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
853     }
854 
855     if (flags & VP8D_DEBUG_TXT_MBLK_MODES)
856     {
857         int i, j;
858         unsigned char *y_ptr;
859         YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
860         int mb_rows = post->y_height >> 4;
861         int mb_cols = post->y_width  >> 4;
862         int mb_index = 0;
863         MODE_INFO *mi = oci->mi;
864 
865         y_ptr = post->y_buffer + 4 * post->y_stride + 4;
866 
867         /* vp8_filter each macro block */
868         for (i = 0; i < mb_rows; i++)
869         {
870             for (j = 0; j < mb_cols; j++)
871             {
872                 char zz[4];
873 
874                 sprintf(zz, "%c", mi[mb_index].mbmi.mode + 'a');
875 
876                 vp8_blit_text(zz, y_ptr, post->y_stride);
877                 mb_index ++;
878                 y_ptr += 16;
879             }
880 
881             mb_index ++; /* border */
882             y_ptr += post->y_stride  * 16 - post->y_width;
883 
884         }
885     }
886 
887     if (flags & VP8D_DEBUG_TXT_DC_DIFF)
888     {
889         int i, j;
890         unsigned char *y_ptr;
891         YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
892         int mb_rows = post->y_height >> 4;
893         int mb_cols = post->y_width  >> 4;
894         int mb_index = 0;
895         MODE_INFO *mi = oci->mi;
896 
897         y_ptr = post->y_buffer + 4 * post->y_stride + 4;
898 
899         /* vp8_filter each macro block */
900         for (i = 0; i < mb_rows; i++)
901         {
902             for (j = 0; j < mb_cols; j++)
903             {
904                 char zz[4];
905                 int dc_diff = !(mi[mb_index].mbmi.mode != B_PRED &&
906                               mi[mb_index].mbmi.mode != SPLITMV &&
907                               mi[mb_index].mbmi.mb_skip_coeff);
908 
909                 if (oci->frame_type == KEY_FRAME)
910                     sprintf(zz, "a");
911                 else
912                     sprintf(zz, "%c", dc_diff + '0');
913 
914                 vp8_blit_text(zz, y_ptr, post->y_stride);
915                 mb_index ++;
916                 y_ptr += 16;
917             }
918 
919             mb_index ++; /* border */
920             y_ptr += post->y_stride  * 16 - post->y_width;
921 
922         }
923     }
924 
925     if (flags & VP8D_DEBUG_TXT_RATE_INFO)
926     {
927         char message[512];
928         sprintf(message, "Bitrate: %10.2f framerate: %10.2f ", oci->bitrate, oci->framerate);
929         vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
930     }
931 
932     /* Draw motion vectors */
933     if ((flags & VP8D_DEBUG_DRAW_MV) && ppflags->display_mv_flag)
934     {
935         YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
936         int width  = post->y_width;
937         int height = post->y_height;
938         unsigned char *y_buffer = oci->post_proc_buffer.y_buffer;
939         int y_stride = oci->post_proc_buffer.y_stride;
940         MODE_INFO *mi = oci->mi;
941         int x0, y0;
942 
943         for (y0 = 0; y0 < height; y0 += 16)
944         {
945             for (x0 = 0; x0 < width; x0 += 16)
946             {
947                 int x1, y1;
948 
949                 if (!(ppflags->display_mv_flag & (1<<mi->mbmi.mode)))
950                 {
951                     mi++;
952                     continue;
953                 }
954 
955                 if (mi->mbmi.mode == SPLITMV)
956                 {
957                     switch (mi->mbmi.partitioning)
958                     {
959                         case 0 :    /* mv_top_bottom */
960                         {
961                             union b_mode_info *bmi = &mi->bmi[0];
962                             MV *mv = &bmi->mv.as_mv;
963 
964                             x1 = x0 + 8 + (mv->col >> 3);
965                             y1 = y0 + 4 + (mv->row >> 3);
966 
967                             constrain_line (x0+8, &x1, y0+4, &y1, width, height);
968                             vp8_blit_line  (x0+8,  x1, y0+4,  y1, y_buffer, y_stride);
969 
970                             bmi = &mi->bmi[8];
971 
972                             x1 = x0 + 8 + (mv->col >> 3);
973                             y1 = y0 +12 + (mv->row >> 3);
974 
975                             constrain_line (x0+8, &x1, y0+12, &y1, width, height);
976                             vp8_blit_line  (x0+8,  x1, y0+12,  y1, y_buffer, y_stride);
977 
978                             break;
979                         }
980                         case 1 :    /* mv_left_right */
981                         {
982                             union b_mode_info *bmi = &mi->bmi[0];
983                             MV *mv = &bmi->mv.as_mv;
984 
985                             x1 = x0 + 4 + (mv->col >> 3);
986                             y1 = y0 + 8 + (mv->row >> 3);
987 
988                             constrain_line (x0+4, &x1, y0+8, &y1, width, height);
989                             vp8_blit_line  (x0+4,  x1, y0+8,  y1, y_buffer, y_stride);
990 
991                             bmi = &mi->bmi[2];
992 
993                             x1 = x0 +12 + (mv->col >> 3);
994                             y1 = y0 + 8 + (mv->row >> 3);
995 
996                             constrain_line (x0+12, &x1, y0+8, &y1, width, height);
997                             vp8_blit_line  (x0+12,  x1, y0+8,  y1, y_buffer, y_stride);
998 
999                             break;
1000                         }
1001                         case 2 :    /* mv_quarters   */
1002                         {
1003                             union b_mode_info *bmi = &mi->bmi[0];
1004                             MV *mv = &bmi->mv.as_mv;
1005 
1006                             x1 = x0 + 4 + (mv->col >> 3);
1007                             y1 = y0 + 4 + (mv->row >> 3);
1008 
1009                             constrain_line (x0+4, &x1, y0+4, &y1, width, height);
1010                             vp8_blit_line  (x0+4,  x1, y0+4,  y1, y_buffer, y_stride);
1011 
1012                             bmi = &mi->bmi[2];
1013 
1014                             x1 = x0 +12 + (mv->col >> 3);
1015                             y1 = y0 + 4 + (mv->row >> 3);
1016 
1017                             constrain_line (x0+12, &x1, y0+4, &y1, width, height);
1018                             vp8_blit_line  (x0+12,  x1, y0+4,  y1, y_buffer, y_stride);
1019 
1020                             bmi = &mi->bmi[8];
1021 
1022                             x1 = x0 + 4 + (mv->col >> 3);
1023                             y1 = y0 +12 + (mv->row >> 3);
1024 
1025                             constrain_line (x0+4, &x1, y0+12, &y1, width, height);
1026                             vp8_blit_line  (x0+4,  x1, y0+12,  y1, y_buffer, y_stride);
1027 
1028                             bmi = &mi->bmi[10];
1029 
1030                             x1 = x0 +12 + (mv->col >> 3);
1031                             y1 = y0 +12 + (mv->row >> 3);
1032 
1033                             constrain_line (x0+12, &x1, y0+12, &y1, width, height);
1034                             vp8_blit_line  (x0+12,  x1, y0+12,  y1, y_buffer, y_stride);
1035                             break;
1036                         }
1037                         default :
1038                         {
1039                             union b_mode_info *bmi = mi->bmi;
1040                             int bx0, by0;
1041 
1042                             for (by0 = y0; by0 < (y0+16); by0 += 4)
1043                             {
1044                                 for (bx0 = x0; bx0 < (x0+16); bx0 += 4)
1045                                 {
1046                                     MV *mv = &bmi->mv.as_mv;
1047 
1048                                     x1 = bx0 + 2 + (mv->col >> 3);
1049                                     y1 = by0 + 2 + (mv->row >> 3);
1050 
1051                                     constrain_line (bx0+2, &x1, by0+2, &y1, width, height);
1052                                     vp8_blit_line  (bx0+2,  x1, by0+2,  y1, y_buffer, y_stride);
1053 
1054                                     bmi++;
1055                                 }
1056                             }
1057                         }
1058                     }
1059                 }
1060                 else if (mi->mbmi.mode >= NEARESTMV)
1061                 {
1062                     MV *mv = &mi->mbmi.mv.as_mv;
1063                     const int lx0 = x0 + 8;
1064                     const int ly0 = y0 + 8;
1065 
1066                     x1 = lx0 + (mv->col >> 3);
1067                     y1 = ly0 + (mv->row >> 3);
1068 
1069                     if (x1 != lx0 && y1 != ly0)
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                         constrain_line (lx0, &x1, ly0+1, &y1, width, height);
1075                         vp8_blit_line  (lx0,  x1, ly0+1,  y1, y_buffer, y_stride);
1076                     }
1077                     else
1078                         vp8_blit_line  (lx0,  x1, ly0,  y1, y_buffer, y_stride);
1079                 }
1080 
1081                 mi++;
1082             }
1083             mi++;
1084         }
1085     }
1086 
1087     /* Color in block modes */
1088     if ((flags & VP8D_DEBUG_CLR_BLK_MODES)
1089         && (ppflags->display_mb_modes_flag || ppflags->display_b_modes_flag))
1090     {
1091         int y, x;
1092         YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
1093         int width  = post->y_width;
1094         int height = post->y_height;
1095         unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
1096         unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
1097         unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
1098         int y_stride = oci->post_proc_buffer.y_stride;
1099         MODE_INFO *mi = oci->mi;
1100 
1101         for (y = 0; y < height; y += 16)
1102         {
1103             for (x = 0; x < width; x += 16)
1104             {
1105                 int Y = 0, U = 0, V = 0;
1106 
1107                 if (mi->mbmi.mode == B_PRED &&
1108                     ((ppflags->display_mb_modes_flag & B_PRED) || ppflags->display_b_modes_flag))
1109                 {
1110                     int by, bx;
1111                     unsigned char *yl, *ul, *vl;
1112                     union b_mode_info *bmi = mi->bmi;
1113 
1114                     yl = y_ptr + x;
1115                     ul = u_ptr + (x>>1);
1116                     vl = v_ptr + (x>>1);
1117 
1118                     for (by = 0; by < 16; by += 4)
1119                     {
1120                         for (bx = 0; bx < 16; bx += 4)
1121                         {
1122                             if ((ppflags->display_b_modes_flag & (1<<mi->mbmi.mode))
1123                                 || (ppflags->display_mb_modes_flag & B_PRED))
1124                             {
1125                                 Y = B_PREDICTION_MODE_colors[bmi->as_mode][0];
1126                                 U = B_PREDICTION_MODE_colors[bmi->as_mode][1];
1127                                 V = B_PREDICTION_MODE_colors[bmi->as_mode][2];
1128 
1129                                 vp8_blend_b
1130                                     (yl+bx, ul+(bx>>1), vl+(bx>>1), Y, U, V, 0xc000, y_stride);
1131                             }
1132                             bmi++;
1133                         }
1134 
1135                         yl += y_stride*4;
1136                         ul += y_stride*1;
1137                         vl += y_stride*1;
1138                     }
1139                 }
1140                 else if (ppflags->display_mb_modes_flag & (1<<mi->mbmi.mode))
1141                 {
1142                     Y = MB_PREDICTION_MODE_colors[mi->mbmi.mode][0];
1143                     U = MB_PREDICTION_MODE_colors[mi->mbmi.mode][1];
1144                     V = MB_PREDICTION_MODE_colors[mi->mbmi.mode][2];
1145 
1146                     vp8_blend_mb_inner
1147                         (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1148                 }
1149 
1150                 mi++;
1151             }
1152             y_ptr += y_stride*16;
1153             u_ptr += y_stride*4;
1154             v_ptr += y_stride*4;
1155 
1156             mi++;
1157         }
1158     }
1159 
1160     /* Color in frame reference blocks */
1161     if ((flags & VP8D_DEBUG_CLR_FRM_REF_BLKS) && ppflags->display_ref_frame_flag)
1162     {
1163         int y, x;
1164         YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
1165         int width  = post->y_width;
1166         int height = post->y_height;
1167         unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
1168         unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
1169         unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
1170         int y_stride = oci->post_proc_buffer.y_stride;
1171         MODE_INFO *mi = oci->mi;
1172 
1173         for (y = 0; y < height; y += 16)
1174         {
1175             for (x = 0; x < width; x +=16)
1176             {
1177                 int Y = 0, U = 0, V = 0;
1178 
1179                 if (ppflags->display_ref_frame_flag & (1<<mi->mbmi.ref_frame))
1180                 {
1181                     Y = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][0];
1182                     U = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][1];
1183                     V = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][2];
1184 
1185                     vp8_blend_mb_outer
1186                         (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1187                 }
1188 
1189                 mi++;
1190             }
1191             y_ptr += y_stride*16;
1192             u_ptr += y_stride*4;
1193             v_ptr += y_stride*4;
1194 
1195             mi++;
1196         }
1197     }
1198 #endif
1199 
1200     *dest = oci->post_proc_buffer;
1201 
1202     /* handle problem with extending borders */
1203     dest->y_width = oci->Width;
1204     dest->y_height = oci->Height;
1205     dest->uv_height = dest->y_height / 2;
1206     return 0;
1207 }
1208 #endif
1209