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 }
vp8_mbpost_proc_across_ip_c(unsigned char * src,int pitch,int rows,int cols,int flimit)217 void vp8_mbpost_proc_across_ip_c(unsigned char *src, int pitch, int rows, int cols, int flimit)
218 {
219     int r, c, i;
220 
221     unsigned char *s = src;
222     unsigned char d[16];
223 
224     for (r = 0; r < rows; r++)
225     {
226         int sumsq = 0;
227         int sum   = 0;
228 
229         for (i = -8; i<0; i++)
230           s[i]=s[0];
231 
232         /* 17 avoids valgrind warning - we buffer values in c in d
233          * and only write them when we've read 8 ahead...
234          */
235         for (i = cols; i<cols+17; i++)
236           s[i]=s[cols-1];
237 
238         for (i = -8; i <= 6; i++)
239         {
240             sumsq += s[i] * s[i];
241             sum   += s[i];
242             d[i+8] = 0;
243         }
244 
245         for (c = 0; c < cols + 8; c++)
246         {
247             int x = s[c+7] - s[c-8];
248             int y = s[c+7] + s[c-8];
249 
250             sum  += x;
251             sumsq += x * y;
252 
253             d[c&15] = s[c];
254 
255             if (sumsq * 15 - sum * sum < flimit)
256             {
257                 d[c&15] = (8 + sum + s[c]) >> 4;
258             }
259 
260             s[c-8] = d[(c-8)&15];
261         }
262 
263         s += pitch;
264     }
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 = rows; i < rows+17; i++)
288           s[i*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 
388 #if !(CONFIG_TEMPORAL_DENOISING)
vp8_de_noise(VP8_COMMON * cm,YV12_BUFFER_CONFIG * source,YV12_BUFFER_CONFIG * post,int q,int low_var_thresh,int flag)389 void vp8_de_noise(VP8_COMMON                 *cm,
390                   YV12_BUFFER_CONFIG         *source,
391                   YV12_BUFFER_CONFIG         *post,
392                   int                         q,
393                   int                         low_var_thresh,
394                   int                         flag)
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 
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, 8);
420         vp8_post_proc_down_and_across_mb_row(
421             source->v_buffer + 8 * mbr * source->uv_stride,
422             source->v_buffer + 8 * mbr * source->uv_stride,
423             source->uv_stride, source->uv_stride, source->uv_width, limits, 8);
424     }
425 }
426 #endif
427 
vp8_gaussian(double sigma,double mu,double x)428 double vp8_gaussian(double sigma, double mu, double x)
429 {
430     return 1 / (sigma * sqrt(2.0 * 3.14159265)) *
431            (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma)));
432 }
433 
fillrd(struct postproc_state * state,int q,int a)434 static void fillrd(struct postproc_state *state, int q, int a)
435 {
436     char char_dist[300];
437 
438     double sigma;
439     int i;
440 
441     vp8_clear_system_state();
442 
443 
444     sigma = a + .5 + .6 * (63 - q) / 63.0;
445 
446     /* set up a lookup table of 256 entries that matches
447      * a gaussian distribution with sigma determined by q.
448      */
449     {
450         int next, j;
451 
452         next = 0;
453 
454         for (i = -32; i < 32; i++)
455         {
456             const int v = (int)(.5 + 256 * vp8_gaussian(sigma, 0, i));
457 
458             if (v)
459             {
460                 for (j = 0; j < v; j++)
461                 {
462                     char_dist[next+j] = (char) i;
463                 }
464 
465                 next = next + j;
466             }
467 
468         }
469 
470         for (; next < 256; next++)
471             char_dist[next] = 0;
472 
473     }
474 
475     for (i = 0; i < 3072; i++)
476     {
477         state->noise[i] = char_dist[rand() & 0xff];
478     }
479 
480     for (i = 0; i < 16; i++)
481     {
482         state->blackclamp[i] = -char_dist[0];
483         state->whiteclamp[i] = -char_dist[0];
484         state->bothclamp[i] = -2 * char_dist[0];
485     }
486 
487     state->last_q = q;
488     state->last_noise = a;
489 }
490 
491 /****************************************************************************
492  *
493  *  ROUTINE       : plane_add_noise_c
494  *
495  *  INPUTS        : unsigned char *Start    starting address of buffer to add gaussian
496  *                                  noise to
497  *                  unsigned int Width    width of plane
498  *                  unsigned int Height   height of plane
499  *                  int  Pitch    distance between subsequent lines of frame
500  *                  int  q        quantizer used to determine amount of noise
501  *                                  to add
502  *
503  *  OUTPUTS       : None.
504  *
505  *  RETURNS       : void.
506  *
507  *  FUNCTION      : adds gaussian noise to a plane of pixels
508  *
509  *  SPECIAL NOTES : None.
510  *
511  ****************************************************************************/
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)512 void vp8_plane_add_noise_c(unsigned char *Start, char *noise,
513                            char blackclamp[16],
514                            char whiteclamp[16],
515                            char bothclamp[16],
516                            unsigned int Width, unsigned int Height, int Pitch)
517 {
518     unsigned int i, j;
519 
520     for (i = 0; i < Height; i++)
521     {
522         unsigned char *Pos = Start + i * Pitch;
523         char  *Ref = (char *)(noise + (rand() & 0xff));
524 
525         for (j = 0; j < Width; j++)
526         {
527             if (Pos[j] < blackclamp[0])
528                 Pos[j] = blackclamp[0];
529 
530             if (Pos[j] > 255 + whiteclamp[0])
531                 Pos[j] = 255 + whiteclamp[0];
532 
533             Pos[j] += Ref[j];
534         }
535     }
536 }
537 
538 /* Blend the macro block with a solid colored square.  Leave the
539  * edges unblended to give distinction to macro blocks in areas
540  * filled with the same color block.
541  */
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)542 void vp8_blend_mb_inner_c (unsigned char *y, unsigned char *u, unsigned char *v,
543                         int y_1, int u_1, int v_1, int alpha, int stride)
544 {
545     int i, j;
546     int y1_const = y_1*((1<<16)-alpha);
547     int u1_const = u_1*((1<<16)-alpha);
548     int v1_const = v_1*((1<<16)-alpha);
549 
550     y += 2*stride + 2;
551     for (i = 0; i < 12; i++)
552     {
553         for (j = 0; j < 12; j++)
554         {
555             y[j] = (y[j]*alpha + y1_const)>>16;
556         }
557         y += stride;
558     }
559 
560     stride >>= 1;
561 
562     u += stride + 1;
563     v += stride + 1;
564 
565     for (i = 0; i < 6; i++)
566     {
567         for (j = 0; j < 6; j++)
568         {
569             u[j] = (u[j]*alpha + u1_const)>>16;
570             v[j] = (v[j]*alpha + v1_const)>>16;
571         }
572         u += stride;
573         v += stride;
574     }
575 }
576 
577 /* Blend only the edge of the macro block.  Leave center
578  * unblended to allow for other visualizations to be layered.
579  */
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)580 void vp8_blend_mb_outer_c (unsigned char *y, unsigned char *u, unsigned char *v,
581                         int y_1, int u_1, int v_1, int alpha, int stride)
582 {
583     int i, j;
584     int y1_const = y_1*((1<<16)-alpha);
585     int u1_const = u_1*((1<<16)-alpha);
586     int v1_const = v_1*((1<<16)-alpha);
587 
588     for (i = 0; i < 2; i++)
589     {
590         for (j = 0; j < 16; j++)
591         {
592             y[j] = (y[j]*alpha + y1_const)>>16;
593         }
594         y += stride;
595     }
596 
597     for (i = 0; i < 12; i++)
598     {
599         y[0]  = (y[0]*alpha  + y1_const)>>16;
600         y[1]  = (y[1]*alpha  + y1_const)>>16;
601         y[14] = (y[14]*alpha + y1_const)>>16;
602         y[15] = (y[15]*alpha + y1_const)>>16;
603         y += stride;
604     }
605 
606     for (i = 0; i < 2; i++)
607     {
608         for (j = 0; j < 16; j++)
609         {
610             y[j] = (y[j]*alpha + y1_const)>>16;
611         }
612         y += stride;
613     }
614 
615     stride >>= 1;
616 
617     for (j = 0; j < 8; j++)
618     {
619         u[j] = (u[j]*alpha + u1_const)>>16;
620         v[j] = (v[j]*alpha + v1_const)>>16;
621     }
622     u += stride;
623     v += stride;
624 
625     for (i = 0; i < 6; i++)
626     {
627         u[0] = (u[0]*alpha + u1_const)>>16;
628         v[0] = (v[0]*alpha + v1_const)>>16;
629 
630         u[7] = (u[7]*alpha + u1_const)>>16;
631         v[7] = (v[7]*alpha + v1_const)>>16;
632 
633         u += stride;
634         v += stride;
635     }
636 
637     for (j = 0; j < 8; j++)
638     {
639         u[j] = (u[j]*alpha + u1_const)>>16;
640         v[j] = (v[j]*alpha + v1_const)>>16;
641     }
642 }
643 
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)644 void vp8_blend_b_c (unsigned char *y, unsigned char *u, unsigned char *v,
645                         int y_1, int u_1, int v_1, int alpha, int stride)
646 {
647     int i, j;
648     int y1_const = y_1*((1<<16)-alpha);
649     int u1_const = u_1*((1<<16)-alpha);
650     int v1_const = v_1*((1<<16)-alpha);
651 
652     for (i = 0; i < 4; i++)
653     {
654         for (j = 0; j < 4; j++)
655         {
656             y[j] = (y[j]*alpha + y1_const)>>16;
657         }
658         y += stride;
659     }
660 
661     stride >>= 1;
662 
663     for (i = 0; i < 2; i++)
664     {
665         for (j = 0; j < 2; j++)
666         {
667             u[j] = (u[j]*alpha + u1_const)>>16;
668             v[j] = (v[j]*alpha + v1_const)>>16;
669         }
670         u += stride;
671         v += stride;
672     }
673 }
674 
constrain_line(int x_0,int * x_1,int y_0,int * y_1,int width,int height)675 static void constrain_line (int x_0, int *x_1, int y_0, int *y_1, int width, int height)
676 {
677     int dx;
678     int dy;
679 
680     if (*x_1 > width)
681     {
682         dx = *x_1 - x_0;
683         dy = *y_1 - y_0;
684 
685         *x_1 = width;
686         if (dx)
687             *y_1 = ((width-x_0)*dy)/dx + y_0;
688     }
689     if (*x_1 < 0)
690     {
691         dx = *x_1 - x_0;
692         dy = *y_1 - y_0;
693 
694         *x_1 = 0;
695         if (dx)
696             *y_1 = ((0-x_0)*dy)/dx + y_0;
697     }
698     if (*y_1 > height)
699     {
700         dx = *x_1 - x_0;
701         dy = *y_1 - y_0;
702 
703         *y_1 = height;
704         if (dy)
705             *x_1 = ((height-y_0)*dx)/dy + x_0;
706     }
707     if (*y_1 < 0)
708     {
709         dx = *x_1 - x_0;
710         dy = *y_1 - y_0;
711 
712         *y_1 = 0;
713         if (dy)
714             *x_1 = ((0-y_0)*dx)/dy + x_0;
715     }
716 }
717 
718 #if CONFIG_POSTPROC
vp8_post_proc_frame(VP8_COMMON * oci,YV12_BUFFER_CONFIG * dest,vp8_ppflags_t * ppflags)719 int vp8_post_proc_frame(VP8_COMMON *oci, YV12_BUFFER_CONFIG *dest, vp8_ppflags_t *ppflags)
720 {
721     int q = oci->filter_level * 10 / 6;
722     int flags = ppflags->post_proc_flag;
723     int deblock_level = ppflags->deblocking_level;
724     int noise_level = ppflags->noise_level;
725 
726     if (!oci->frame_to_show)
727         return -1;
728 
729     if (q > 63)
730         q = 63;
731 
732     if (!flags)
733     {
734         *dest = *oci->frame_to_show;
735 
736         /* handle problem with extending borders */
737         dest->y_width = oci->Width;
738         dest->y_height = oci->Height;
739         dest->uv_height = dest->y_height / 2;
740         oci->postproc_state.last_base_qindex = oci->base_qindex;
741         oci->postproc_state.last_frame_valid = 1;
742         return 0;
743     }
744 
745     /* Allocate post_proc_buffer_int if needed */
746     if ((flags & VP8D_MFQE) && !oci->post_proc_buffer_int_used)
747     {
748         if ((flags & VP8D_DEBLOCK) || (flags & VP8D_DEMACROBLOCK))
749         {
750             int width = (oci->Width + 15) & ~15;
751             int height = (oci->Height + 15) & ~15;
752 
753             if (vp8_yv12_alloc_frame_buffer(&oci->post_proc_buffer_int,
754                                             width, height, VP8BORDERINPIXELS))
755                 vpx_internal_error(&oci->error, VPX_CODEC_MEM_ERROR,
756                                    "Failed to allocate MFQE framebuffer");
757 
758             oci->post_proc_buffer_int_used = 1;
759 
760             /* insure that postproc is set to all 0's so that post proc
761              * doesn't pull random data in from edge
762              */
763             vpx_memset((&oci->post_proc_buffer_int)->buffer_alloc,128,(&oci->post_proc_buffer)->frame_size);
764 
765         }
766     }
767 
768     vp8_clear_system_state();
769 
770     if ((flags & VP8D_MFQE) &&
771          oci->postproc_state.last_frame_valid &&
772          oci->current_video_frame >= 2 &&
773          oci->postproc_state.last_base_qindex < 60 &&
774          oci->base_qindex - oci->postproc_state.last_base_qindex >= 20)
775     {
776         vp8_multiframe_quality_enhance(oci);
777         if (((flags & VP8D_DEBLOCK) || (flags & VP8D_DEMACROBLOCK)) &&
778             oci->post_proc_buffer_int_used)
779         {
780             vp8_yv12_copy_frame(&oci->post_proc_buffer, &oci->post_proc_buffer_int);
781             if (flags & VP8D_DEMACROBLOCK)
782             {
783                 vp8_deblock(oci, &oci->post_proc_buffer_int, &oci->post_proc_buffer,
784                                                q + (deblock_level - 5) * 10, 1, 0);
785                 vp8_de_mblock(&oci->post_proc_buffer,
786                               q + (deblock_level - 5) * 10);
787             }
788             else if (flags & VP8D_DEBLOCK)
789             {
790                 vp8_deblock(oci, &oci->post_proc_buffer_int, &oci->post_proc_buffer,
791                             q, 1, 0);
792             }
793         }
794         /* Move partially towards the base q of the previous frame */
795         oci->postproc_state.last_base_qindex = (3*oci->postproc_state.last_base_qindex + oci->base_qindex)>>2;
796     }
797     else if (flags & VP8D_DEMACROBLOCK)
798     {
799         vp8_deblock(oci, oci->frame_to_show, &oci->post_proc_buffer,
800                                      q + (deblock_level - 5) * 10, 1, 0);
801         vp8_de_mblock(&oci->post_proc_buffer, q + (deblock_level - 5) * 10);
802 
803         oci->postproc_state.last_base_qindex = oci->base_qindex;
804     }
805     else if (flags & VP8D_DEBLOCK)
806     {
807         vp8_deblock(oci, oci->frame_to_show, &oci->post_proc_buffer,
808                     q, 1, 0);
809         oci->postproc_state.last_base_qindex = oci->base_qindex;
810     }
811     else
812     {
813         vp8_yv12_copy_frame(oci->frame_to_show, &oci->post_proc_buffer);
814         oci->postproc_state.last_base_qindex = oci->base_qindex;
815     }
816     oci->postproc_state.last_frame_valid = 1;
817 
818     if (flags & VP8D_ADDNOISE)
819     {
820         if (oci->postproc_state.last_q != q
821             || oci->postproc_state.last_noise != noise_level)
822         {
823             fillrd(&oci->postproc_state, 63 - q, noise_level);
824         }
825 
826         vp8_plane_add_noise
827         (oci->post_proc_buffer.y_buffer,
828          oci->postproc_state.noise,
829          oci->postproc_state.blackclamp,
830          oci->postproc_state.whiteclamp,
831          oci->postproc_state.bothclamp,
832          oci->post_proc_buffer.y_width, oci->post_proc_buffer.y_height,
833          oci->post_proc_buffer.y_stride);
834     }
835 
836 #if CONFIG_POSTPROC_VISUALIZER
837     if (flags & VP8D_DEBUG_TXT_FRAME_INFO)
838     {
839         char message[512];
840         sprintf(message, "F%1dG%1dQ%3dF%3dP%d_s%dx%d",
841                 (oci->frame_type == KEY_FRAME),
842                 oci->refresh_golden_frame,
843                 oci->base_qindex,
844                 oci->filter_level,
845                 flags,
846                 oci->mb_cols, oci->mb_rows);
847         vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
848     }
849 
850     if (flags & VP8D_DEBUG_TXT_MBLK_MODES)
851     {
852         int i, j;
853         unsigned char *y_ptr;
854         YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
855         int mb_rows = post->y_height >> 4;
856         int mb_cols = post->y_width  >> 4;
857         int mb_index = 0;
858         MODE_INFO *mi = oci->mi;
859 
860         y_ptr = post->y_buffer + 4 * post->y_stride + 4;
861 
862         /* vp8_filter each macro block */
863         for (i = 0; i < mb_rows; i++)
864         {
865             for (j = 0; j < mb_cols; j++)
866             {
867                 char zz[4];
868 
869                 sprintf(zz, "%c", mi[mb_index].mbmi.mode + 'a');
870 
871                 vp8_blit_text(zz, y_ptr, post->y_stride);
872                 mb_index ++;
873                 y_ptr += 16;
874             }
875 
876             mb_index ++; /* border */
877             y_ptr += post->y_stride  * 16 - post->y_width;
878 
879         }
880     }
881 
882     if (flags & VP8D_DEBUG_TXT_DC_DIFF)
883     {
884         int i, j;
885         unsigned char *y_ptr;
886         YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
887         int mb_rows = post->y_height >> 4;
888         int mb_cols = post->y_width  >> 4;
889         int mb_index = 0;
890         MODE_INFO *mi = oci->mi;
891 
892         y_ptr = post->y_buffer + 4 * post->y_stride + 4;
893 
894         /* vp8_filter each macro block */
895         for (i = 0; i < mb_rows; i++)
896         {
897             for (j = 0; j < mb_cols; j++)
898             {
899                 char zz[4];
900                 int dc_diff = !(mi[mb_index].mbmi.mode != B_PRED &&
901                               mi[mb_index].mbmi.mode != SPLITMV &&
902                               mi[mb_index].mbmi.mb_skip_coeff);
903 
904                 if (oci->frame_type == KEY_FRAME)
905                     sprintf(zz, "a");
906                 else
907                     sprintf(zz, "%c", dc_diff + '0');
908 
909                 vp8_blit_text(zz, y_ptr, post->y_stride);
910                 mb_index ++;
911                 y_ptr += 16;
912             }
913 
914             mb_index ++; /* border */
915             y_ptr += post->y_stride  * 16 - post->y_width;
916 
917         }
918     }
919 
920     if (flags & VP8D_DEBUG_TXT_RATE_INFO)
921     {
922         char message[512];
923         sprintf(message, "Bitrate: %10.2f framerate: %10.2f ", oci->bitrate, oci->framerate);
924         vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
925     }
926 
927     /* Draw motion vectors */
928     if ((flags & VP8D_DEBUG_DRAW_MV) && ppflags->display_mv_flag)
929     {
930         YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
931         int width  = post->y_width;
932         int height = post->y_height;
933         unsigned char *y_buffer = oci->post_proc_buffer.y_buffer;
934         int y_stride = oci->post_proc_buffer.y_stride;
935         MODE_INFO *mi = oci->mi;
936         int x0, y0;
937 
938         for (y0 = 0; y0 < height; y0 += 16)
939         {
940             for (x0 = 0; x0 < width; x0 += 16)
941             {
942                 int x1, y1;
943 
944                 if (!(ppflags->display_mv_flag & (1<<mi->mbmi.mode)))
945                 {
946                     mi++;
947                     continue;
948                 }
949 
950                 if (mi->mbmi.mode == SPLITMV)
951                 {
952                     switch (mi->mbmi.partitioning)
953                     {
954                         case 0 :    /* mv_top_bottom */
955                         {
956                             union b_mode_info *bmi = &mi->bmi[0];
957                             MV *mv = &bmi->mv.as_mv;
958 
959                             x1 = x0 + 8 + (mv->col >> 3);
960                             y1 = y0 + 4 + (mv->row >> 3);
961 
962                             constrain_line (x0+8, &x1, y0+4, &y1, width, height);
963                             vp8_blit_line  (x0+8,  x1, y0+4,  y1, y_buffer, y_stride);
964 
965                             bmi = &mi->bmi[8];
966 
967                             x1 = x0 + 8 + (mv->col >> 3);
968                             y1 = y0 +12 + (mv->row >> 3);
969 
970                             constrain_line (x0+8, &x1, y0+12, &y1, width, height);
971                             vp8_blit_line  (x0+8,  x1, y0+12,  y1, y_buffer, y_stride);
972 
973                             break;
974                         }
975                         case 1 :    /* mv_left_right */
976                         {
977                             union b_mode_info *bmi = &mi->bmi[0];
978                             MV *mv = &bmi->mv.as_mv;
979 
980                             x1 = x0 + 4 + (mv->col >> 3);
981                             y1 = y0 + 8 + (mv->row >> 3);
982 
983                             constrain_line (x0+4, &x1, y0+8, &y1, width, height);
984                             vp8_blit_line  (x0+4,  x1, y0+8,  y1, y_buffer, y_stride);
985 
986                             bmi = &mi->bmi[2];
987 
988                             x1 = x0 +12 + (mv->col >> 3);
989                             y1 = y0 + 8 + (mv->row >> 3);
990 
991                             constrain_line (x0+12, &x1, y0+8, &y1, width, height);
992                             vp8_blit_line  (x0+12,  x1, y0+8,  y1, y_buffer, y_stride);
993 
994                             break;
995                         }
996                         case 2 :    /* mv_quarters   */
997                         {
998                             union b_mode_info *bmi = &mi->bmi[0];
999                             MV *mv = &bmi->mv.as_mv;
1000 
1001                             x1 = x0 + 4 + (mv->col >> 3);
1002                             y1 = y0 + 4 + (mv->row >> 3);
1003 
1004                             constrain_line (x0+4, &x1, y0+4, &y1, width, height);
1005                             vp8_blit_line  (x0+4,  x1, y0+4,  y1, y_buffer, y_stride);
1006 
1007                             bmi = &mi->bmi[2];
1008 
1009                             x1 = x0 +12 + (mv->col >> 3);
1010                             y1 = y0 + 4 + (mv->row >> 3);
1011 
1012                             constrain_line (x0+12, &x1, y0+4, &y1, width, height);
1013                             vp8_blit_line  (x0+12,  x1, y0+4,  y1, y_buffer, y_stride);
1014 
1015                             bmi = &mi->bmi[8];
1016 
1017                             x1 = x0 + 4 + (mv->col >> 3);
1018                             y1 = y0 +12 + (mv->row >> 3);
1019 
1020                             constrain_line (x0+4, &x1, y0+12, &y1, width, height);
1021                             vp8_blit_line  (x0+4,  x1, y0+12,  y1, y_buffer, y_stride);
1022 
1023                             bmi = &mi->bmi[10];
1024 
1025                             x1 = x0 +12 + (mv->col >> 3);
1026                             y1 = y0 +12 + (mv->row >> 3);
1027 
1028                             constrain_line (x0+12, &x1, y0+12, &y1, width, height);
1029                             vp8_blit_line  (x0+12,  x1, y0+12,  y1, y_buffer, y_stride);
1030                             break;
1031                         }
1032                         default :
1033                         {
1034                             union b_mode_info *bmi = mi->bmi;
1035                             int bx0, by0;
1036 
1037                             for (by0 = y0; by0 < (y0+16); by0 += 4)
1038                             {
1039                                 for (bx0 = x0; bx0 < (x0+16); bx0 += 4)
1040                                 {
1041                                     MV *mv = &bmi->mv.as_mv;
1042 
1043                                     x1 = bx0 + 2 + (mv->col >> 3);
1044                                     y1 = by0 + 2 + (mv->row >> 3);
1045 
1046                                     constrain_line (bx0+2, &x1, by0+2, &y1, width, height);
1047                                     vp8_blit_line  (bx0+2,  x1, by0+2,  y1, y_buffer, y_stride);
1048 
1049                                     bmi++;
1050                                 }
1051                             }
1052                         }
1053                     }
1054                 }
1055                 else if (mi->mbmi.mode >= NEARESTMV)
1056                 {
1057                     MV *mv = &mi->mbmi.mv.as_mv;
1058                     const int lx0 = x0 + 8;
1059                     const int ly0 = y0 + 8;
1060 
1061                     x1 = lx0 + (mv->col >> 3);
1062                     y1 = ly0 + (mv->row >> 3);
1063 
1064                     if (x1 != lx0 && y1 != ly0)
1065                     {
1066                         constrain_line (lx0, &x1, ly0-1, &y1, width, height);
1067                         vp8_blit_line  (lx0,  x1, ly0-1,  y1, y_buffer, y_stride);
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                     else
1073                         vp8_blit_line  (lx0,  x1, ly0,  y1, y_buffer, y_stride);
1074                 }
1075 
1076                 mi++;
1077             }
1078             mi++;
1079         }
1080     }
1081 
1082     /* Color in block modes */
1083     if ((flags & VP8D_DEBUG_CLR_BLK_MODES)
1084         && (ppflags->display_mb_modes_flag || ppflags->display_b_modes_flag))
1085     {
1086         int y, x;
1087         YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
1088         int width  = post->y_width;
1089         int height = post->y_height;
1090         unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
1091         unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
1092         unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
1093         int y_stride = oci->post_proc_buffer.y_stride;
1094         MODE_INFO *mi = oci->mi;
1095 
1096         for (y = 0; y < height; y += 16)
1097         {
1098             for (x = 0; x < width; x += 16)
1099             {
1100                 int Y = 0, U = 0, V = 0;
1101 
1102                 if (mi->mbmi.mode == B_PRED &&
1103                     ((ppflags->display_mb_modes_flag & B_PRED) || ppflags->display_b_modes_flag))
1104                 {
1105                     int by, bx;
1106                     unsigned char *yl, *ul, *vl;
1107                     union b_mode_info *bmi = mi->bmi;
1108 
1109                     yl = y_ptr + x;
1110                     ul = u_ptr + (x>>1);
1111                     vl = v_ptr + (x>>1);
1112 
1113                     for (by = 0; by < 16; by += 4)
1114                     {
1115                         for (bx = 0; bx < 16; bx += 4)
1116                         {
1117                             if ((ppflags->display_b_modes_flag & (1<<mi->mbmi.mode))
1118                                 || (ppflags->display_mb_modes_flag & B_PRED))
1119                             {
1120                                 Y = B_PREDICTION_MODE_colors[bmi->as_mode][0];
1121                                 U = B_PREDICTION_MODE_colors[bmi->as_mode][1];
1122                                 V = B_PREDICTION_MODE_colors[bmi->as_mode][2];
1123 
1124                                 vp8_blend_b
1125                                     (yl+bx, ul+(bx>>1), vl+(bx>>1), Y, U, V, 0xc000, y_stride);
1126                             }
1127                             bmi++;
1128                         }
1129 
1130                         yl += y_stride*4;
1131                         ul += y_stride*1;
1132                         vl += y_stride*1;
1133                     }
1134                 }
1135                 else if (ppflags->display_mb_modes_flag & (1<<mi->mbmi.mode))
1136                 {
1137                     Y = MB_PREDICTION_MODE_colors[mi->mbmi.mode][0];
1138                     U = MB_PREDICTION_MODE_colors[mi->mbmi.mode][1];
1139                     V = MB_PREDICTION_MODE_colors[mi->mbmi.mode][2];
1140 
1141                     vp8_blend_mb_inner
1142                         (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1143                 }
1144 
1145                 mi++;
1146             }
1147             y_ptr += y_stride*16;
1148             u_ptr += y_stride*4;
1149             v_ptr += y_stride*4;
1150 
1151             mi++;
1152         }
1153     }
1154 
1155     /* Color in frame reference blocks */
1156     if ((flags & VP8D_DEBUG_CLR_FRM_REF_BLKS) && ppflags->display_ref_frame_flag)
1157     {
1158         int y, x;
1159         YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
1160         int width  = post->y_width;
1161         int height = post->y_height;
1162         unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
1163         unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
1164         unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
1165         int y_stride = oci->post_proc_buffer.y_stride;
1166         MODE_INFO *mi = oci->mi;
1167 
1168         for (y = 0; y < height; y += 16)
1169         {
1170             for (x = 0; x < width; x +=16)
1171             {
1172                 int Y = 0, U = 0, V = 0;
1173 
1174                 if (ppflags->display_ref_frame_flag & (1<<mi->mbmi.ref_frame))
1175                 {
1176                     Y = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][0];
1177                     U = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][1];
1178                     V = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][2];
1179 
1180                     vp8_blend_mb_outer
1181                         (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1182                 }
1183 
1184                 mi++;
1185             }
1186             y_ptr += y_stride*16;
1187             u_ptr += y_stride*4;
1188             v_ptr += y_stride*4;
1189 
1190             mi++;
1191         }
1192     }
1193 #endif
1194 
1195     *dest = oci->post_proc_buffer;
1196 
1197     /* handle problem with extending borders */
1198     dest->y_width = oci->Width;
1199     dest->y_height = oci->Height;
1200     dest->uv_height = dest->y_height / 2;
1201     return 0;
1202 }
1203 #endif
1204