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