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