• 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_ports/config.h"
13 #include "vpx_scale/yv12config.h"
14 #include "postproc.h"
15 #include "vpx_scale/yv12extend.h"
16 #include "vpx_scale/vpxscale.h"
17 #include "systemdependent.h"
18 
19 #include <math.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 
23 #define RGB_TO_YUV(t)                                                                       \
24     ( (0.257*(float)(t>>16)) + (0.504*(float)(t>>8&0xff)) + (0.098*(float)(t&0xff)) + 16),  \
25     (-(0.148*(float)(t>>16)) - (0.291*(float)(t>>8&0xff)) + (0.439*(float)(t&0xff)) + 128), \
26     ( (0.439*(float)(t>>16)) - (0.368*(float)(t>>8&0xff)) - (0.071*(float)(t&0xff)) + 128)
27 
28 /* global constants */
29 #if CONFIG_POSTPROC_VISUALIZER
30 static const unsigned char MB_PREDICTION_MODE_colors[MB_MODE_COUNT][3] =
31 {
32     { RGB_TO_YUV(0x98FB98) },   /* PaleGreen */
33     { RGB_TO_YUV(0x00FF00) },   /* Green */
34     { RGB_TO_YUV(0xADFF2F) },   /* GreenYellow */
35     { RGB_TO_YUV(0x228B22) },   /* ForestGreen */
36     { RGB_TO_YUV(0x006400) },   /* DarkGreen */
37     { RGB_TO_YUV(0x98F5FF) },   /* Cadet Blue */
38     { RGB_TO_YUV(0x6CA6CD) },   /* Sky Blue */
39     { RGB_TO_YUV(0x00008B) },   /* Dark blue */
40     { RGB_TO_YUV(0x551A8B) },   /* Purple */
41     { RGB_TO_YUV(0xFF0000) }    /* Red */
42 };
43 
44 static const unsigned char B_PREDICTION_MODE_colors[B_MODE_COUNT][3] =
45 {
46     { RGB_TO_YUV(0x6633ff) },   /* Purple */
47     { RGB_TO_YUV(0xcc33ff) },   /* Magenta */
48     { RGB_TO_YUV(0xff33cc) },   /* Pink */
49     { RGB_TO_YUV(0xff3366) },   /* Coral */
50     { RGB_TO_YUV(0x3366ff) },   /* Blue */
51     { RGB_TO_YUV(0xed00f5) },   /* Dark Blue */
52     { RGB_TO_YUV(0x2e00b8) },   /* Dark Purple */
53     { RGB_TO_YUV(0xff6633) },   /* Orange */
54     { RGB_TO_YUV(0x33ccff) },   /* Light Blue */
55     { RGB_TO_YUV(0x8ab800) },   /* Green */
56     { RGB_TO_YUV(0xffcc33) },   /* Light Orange */
57     { RGB_TO_YUV(0x33ffcc) },   /* Aqua */
58     { RGB_TO_YUV(0x66ff33) },   /* Light Green */
59     { RGB_TO_YUV(0xccff33) },   /* Yellow */
60 };
61 
62 static const unsigned char MV_REFERENCE_FRAME_colors[MAX_REF_FRAMES][3] =
63 {
64     { RGB_TO_YUV(0x00ff00) },   /* Blue */
65     { RGB_TO_YUV(0x0000ff) },   /* Green */
66     { RGB_TO_YUV(0xffff00) },   /* Yellow */
67     { RGB_TO_YUV(0xff0000) },   /* Red */
68 };
69 #endif
70 
71 static const short kernel5[] =
72 {
73     1, 1, 4, 1, 1
74 };
75 
76 const short vp8_rv[] =
77 {
78     8, 5, 2, 2, 8, 12, 4, 9, 8, 3,
79     0, 3, 9, 0, 0, 0, 8, 3, 14, 4,
80     10, 1, 11, 14, 1, 14, 9, 6, 12, 11,
81     8, 6, 10, 0, 0, 8, 9, 0, 3, 14,
82     8, 11, 13, 4, 2, 9, 0, 3, 9, 6,
83     1, 2, 3, 14, 13, 1, 8, 2, 9, 7,
84     3, 3, 1, 13, 13, 6, 6, 5, 2, 7,
85     11, 9, 11, 8, 7, 3, 2, 0, 13, 13,
86     14, 4, 12, 5, 12, 10, 8, 10, 13, 10,
87     4, 14, 4, 10, 0, 8, 11, 1, 13, 7,
88     7, 14, 6, 14, 13, 2, 13, 5, 4, 4,
89     0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
90     8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
91     3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
92     3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
93     13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
94     5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
95     9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
96     4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
97     3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
98     11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
99     5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
100     0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
101     10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
102     4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
103     0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
104     8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
105     3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
106     3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
107     13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
108     5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
109     9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
110     4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
111     3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
112     11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
113     5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
114     0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
115     10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
116     4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
117     3, 8, 3, 7, 8, 5, 11, 4, 12, 3,
118     11, 9, 14, 8, 14, 13, 4, 3, 1, 2,
119     14, 6, 5, 4, 4, 11, 4, 6, 2, 1,
120     5, 8, 8, 12, 13, 5, 14, 10, 12, 13,
121     0, 9, 5, 5, 11, 10, 13, 9, 10, 13,
122 };
123 
124 
125 extern void vp8_blit_text(const char *msg, unsigned char *address, const int pitch);
126 extern void vp8_blit_line(int x0, int x1, int y0, int y1, unsigned char *image, const int pitch);
127 /***********************************************************************************************************
128  */
vp8_post_proc_down_and_across_c(unsigned char * src_ptr,unsigned char * dst_ptr,int src_pixels_per_line,int dst_pixels_per_line,int rows,int cols,int flimit)129 void vp8_post_proc_down_and_across_c
130 (
131     unsigned char *src_ptr,
132     unsigned char *dst_ptr,
133     int src_pixels_per_line,
134     int dst_pixels_per_line,
135     int rows,
136     int cols,
137     int flimit
138 )
139 {
140     unsigned char *p_src, *p_dst;
141     int row;
142     int col;
143     int i;
144     int v;
145     int pitch = src_pixels_per_line;
146     unsigned char d[8];
147     (void)dst_pixels_per_line;
148 
149     for (row = 0; row < rows; row++)
150     {
151         /* post_proc_down for one row */
152         p_src = src_ptr;
153         p_dst = dst_ptr;
154 
155         for (col = 0; col < cols; col++)
156         {
157 
158             int kernel = 4;
159             int v = p_src[col];
160 
161             for (i = -2; i <= 2; i++)
162             {
163                 if (abs(v - p_src[col+i*pitch]) > flimit)
164                     goto down_skip_convolve;
165 
166                 kernel += kernel5[2+i] * p_src[col+i*pitch];
167             }
168 
169             v = (kernel >> 3);
170         down_skip_convolve:
171             p_dst[col] = v;
172         }
173 
174         /* now post_proc_across */
175         p_src = dst_ptr;
176         p_dst = dst_ptr;
177 
178         for (i = 0; i < 8; i++)
179             d[i] = p_src[i];
180 
181         for (col = 0; col < cols; col++)
182         {
183             int kernel = 4;
184             v = p_src[col];
185 
186             d[col&7] = v;
187 
188             for (i = -2; i <= 2; i++)
189             {
190                 if (abs(v - p_src[col+i]) > flimit)
191                     goto across_skip_convolve;
192 
193                 kernel += kernel5[2+i] * p_src[col+i];
194             }
195 
196             d[col&7] = (kernel >> 3);
197         across_skip_convolve:
198 
199             if (col >= 2)
200                 p_dst[col-2] = d[(col-2)&7];
201         }
202 
203         /* handle the last two pixels */
204         p_dst[col-2] = d[(col-2)&7];
205         p_dst[col-1] = d[(col-1)&7];
206 
207 
208         /* next row */
209         src_ptr += pitch;
210         dst_ptr += pitch;
211     }
212 }
213 
q2mbl(int x)214 static int q2mbl(int x)
215 {
216     if (x < 20) x = 20;
217 
218     x = 50 + (x - 50) * 10 / 8;
219     return x * x / 3;
220 }
vp8_mbpost_proc_across_ip_c(unsigned char * src,int pitch,int rows,int cols,int flimit)221 void vp8_mbpost_proc_across_ip_c(unsigned char *src, int pitch, int rows, int cols, int flimit)
222 {
223     int r, c, i;
224 
225     unsigned char *s = src;
226     unsigned char d[16];
227 
228 
229     for (r = 0; r < rows; r++)
230     {
231         int sumsq = 0;
232         int sum   = 0;
233 
234         for (i = -8; i <= 6; i++)
235         {
236             sumsq += s[i] * s[i];
237             sum   += s[i];
238             d[i+8] = 0;
239         }
240 
241         for (c = 0; c < cols + 8; c++)
242         {
243             int x = s[c+7] - s[c-8];
244             int y = s[c+7] + s[c-8];
245 
246             sum  += x;
247             sumsq += x * y;
248 
249             d[c&15] = s[c];
250 
251             if (sumsq * 15 - sum * sum < flimit)
252             {
253                 d[c&15] = (8 + sum + s[c]) >> 4;
254             }
255 
256             s[c-8] = d[(c-8)&15];
257         }
258 
259         s += pitch;
260     }
261 }
262 
263 
264 
265 
266 
vp8_mbpost_proc_down_c(unsigned char * dst,int pitch,int rows,int cols,int flimit)267 void vp8_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols, int flimit)
268 {
269     int r, c, i;
270     const short *rv3 = &vp8_rv[63&rand()];
271 
272     for (c = 0; c < cols; c++)
273     {
274         unsigned char *s = &dst[c];
275         int sumsq = 0;
276         int sum   = 0;
277         unsigned char d[16];
278         const short *rv2 = rv3 + ((c * 17) & 127);
279 
280         for (i = -8; i <= 6; i++)
281         {
282             sumsq += s[i*pitch] * s[i*pitch];
283             sum   += s[i*pitch];
284         }
285 
286         for (r = 0; r < rows + 8; r++)
287         {
288             sumsq += s[7*pitch] * s[ 7*pitch] - s[-8*pitch] * s[-8*pitch];
289             sum  += s[7*pitch] - s[-8*pitch];
290             d[r&15] = s[0];
291 
292             if (sumsq * 15 - sum * sum < flimit)
293             {
294                 d[r&15] = (rv2[r&127] + sum + s[0]) >> 4;
295             }
296 
297             s[-8*pitch] = d[(r-8)&15];
298             s += pitch;
299         }
300     }
301 }
302 
303 
vp8_deblock_and_de_macro_block(YV12_BUFFER_CONFIG * source,YV12_BUFFER_CONFIG * post,int q,int low_var_thresh,int flag,vp8_postproc_rtcd_vtable_t * rtcd)304 static void vp8_deblock_and_de_macro_block(YV12_BUFFER_CONFIG         *source,
305         YV12_BUFFER_CONFIG         *post,
306         int                         q,
307         int                         low_var_thresh,
308         int                         flag,
309         vp8_postproc_rtcd_vtable_t *rtcd)
310 {
311     double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
312     int ppl = (int)(level + .5);
313     (void) low_var_thresh;
314     (void) flag;
315 
316     POSTPROC_INVOKE(rtcd, downacross)(source->y_buffer, post->y_buffer, source->y_stride,  post->y_stride, source->y_height, source->y_width,  ppl);
317     POSTPROC_INVOKE(rtcd, across)(post->y_buffer, post->y_stride, post->y_height, post->y_width, q2mbl(q));
318     POSTPROC_INVOKE(rtcd, down)(post->y_buffer, post->y_stride, post->y_height, post->y_width, q2mbl(q));
319 
320     POSTPROC_INVOKE(rtcd, downacross)(source->u_buffer, post->u_buffer, source->uv_stride, post->uv_stride, source->uv_height, source->uv_width, ppl);
321     POSTPROC_INVOKE(rtcd, downacross)(source->v_buffer, post->v_buffer, source->uv_stride, post->uv_stride, source->uv_height, source->uv_width, ppl);
322 
323 }
324 
vp8_deblock(YV12_BUFFER_CONFIG * source,YV12_BUFFER_CONFIG * post,int q,int low_var_thresh,int flag,vp8_postproc_rtcd_vtable_t * rtcd)325 void vp8_deblock(YV12_BUFFER_CONFIG         *source,
326                         YV12_BUFFER_CONFIG         *post,
327                         int                         q,
328                         int                         low_var_thresh,
329                         int                         flag,
330                         vp8_postproc_rtcd_vtable_t *rtcd)
331 {
332     double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
333     int ppl = (int)(level + .5);
334     (void) low_var_thresh;
335     (void) flag;
336 
337     POSTPROC_INVOKE(rtcd, downacross)(source->y_buffer, post->y_buffer, source->y_stride,  post->y_stride, source->y_height, source->y_width,   ppl);
338     POSTPROC_INVOKE(rtcd, downacross)(source->u_buffer, post->u_buffer, source->uv_stride, post->uv_stride,  source->uv_height, source->uv_width, ppl);
339     POSTPROC_INVOKE(rtcd, downacross)(source->v_buffer, post->v_buffer, source->uv_stride, post->uv_stride, source->uv_height, source->uv_width, ppl);
340 }
341 
vp8_de_noise(YV12_BUFFER_CONFIG * source,YV12_BUFFER_CONFIG * post,int q,int low_var_thresh,int flag,vp8_postproc_rtcd_vtable_t * rtcd)342 void vp8_de_noise(YV12_BUFFER_CONFIG         *source,
343                   YV12_BUFFER_CONFIG         *post,
344                   int                         q,
345                   int                         low_var_thresh,
346                   int                         flag,
347                   vp8_postproc_rtcd_vtable_t *rtcd)
348 {
349     double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
350     int ppl = (int)(level + .5);
351     (void) post;
352     (void) low_var_thresh;
353     (void) flag;
354 
355     POSTPROC_INVOKE(rtcd, downacross)(
356         source->y_buffer + 2 * source->y_stride + 2,
357         source->y_buffer + 2 * source->y_stride + 2,
358         source->y_stride,
359         source->y_stride,
360         source->y_height - 4,
361         source->y_width - 4,
362         ppl);
363     POSTPROC_INVOKE(rtcd, downacross)(
364         source->u_buffer + 2 * source->uv_stride + 2,
365         source->u_buffer + 2 * source->uv_stride + 2,
366         source->uv_stride,
367         source->uv_stride,
368         source->uv_height - 4,
369         source->uv_width - 4, ppl);
370     POSTPROC_INVOKE(rtcd, downacross)(
371         source->v_buffer + 2 * source->uv_stride + 2,
372         source->v_buffer + 2 * source->uv_stride + 2,
373         source->uv_stride,
374         source->uv_stride,
375         source->uv_height - 4,
376         source->uv_width - 4, ppl);
377 
378 }
379 
vp8_gaussian(double sigma,double mu,double x)380 double vp8_gaussian(double sigma, double mu, double x)
381 {
382     return 1 / (sigma * sqrt(2.0 * 3.14159265)) *
383            (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma)));
384 }
385 
386 extern void (*vp8_clear_system_state)(void);
387 
388 
fillrd(struct postproc_state * state,int q,int a)389 static void fillrd(struct postproc_state *state, int q, int a)
390 {
391     char char_dist[300];
392 
393     double sigma;
394     int ai = a, qi = q, i;
395 
396     vp8_clear_system_state();
397 
398 
399     sigma = ai + .5 + .6 * (63 - qi) / 63.0;
400 
401     /* set up a lookup table of 256 entries that matches
402      * a gaussian distribution with sigma determined by q.
403      */
404     {
405         double i;
406         int next, j;
407 
408         next = 0;
409 
410         for (i = -32; i < 32; i++)
411         {
412             int a = (int)(.5 + 256 * vp8_gaussian(sigma, 0, i));
413 
414             if (a)
415             {
416                 for (j = 0; j < a; j++)
417                 {
418                     char_dist[next+j] = (char) i;
419                 }
420 
421                 next = next + j;
422             }
423 
424         }
425 
426         for (next = next; next < 256; next++)
427             char_dist[next] = 0;
428 
429     }
430 
431     for (i = 0; i < 3072; i++)
432     {
433         state->noise[i] = char_dist[rand() & 0xff];
434     }
435 
436     for (i = 0; i < 16; i++)
437     {
438         state->blackclamp[i] = -char_dist[0];
439         state->whiteclamp[i] = -char_dist[0];
440         state->bothclamp[i] = -2 * char_dist[0];
441     }
442 
443     state->last_q = q;
444     state->last_noise = a;
445 }
446 
447 /****************************************************************************
448  *
449  *  ROUTINE       : plane_add_noise_c
450  *
451  *  INPUTS        : unsigned char *Start    starting address of buffer to add gaussian
452  *                                  noise to
453  *                  unsigned int Width    width of plane
454  *                  unsigned int Height   height of plane
455  *                  int  Pitch    distance between subsequent lines of frame
456  *                  int  q        quantizer used to determine amount of noise
457  *                                  to add
458  *
459  *  OUTPUTS       : None.
460  *
461  *  RETURNS       : void.
462  *
463  *  FUNCTION      : adds gaussian noise to a plane of pixels
464  *
465  *  SPECIAL NOTES : None.
466  *
467  ****************************************************************************/
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)468 void vp8_plane_add_noise_c(unsigned char *Start, char *noise,
469                            char blackclamp[16],
470                            char whiteclamp[16],
471                            char bothclamp[16],
472                            unsigned int Width, unsigned int Height, int Pitch)
473 {
474     unsigned int i, j;
475 
476     for (i = 0; i < Height; i++)
477     {
478         unsigned char *Pos = Start + i * Pitch;
479         char  *Ref = (char *)(noise + (rand() & 0xff));
480 
481         for (j = 0; j < Width; j++)
482         {
483             if (Pos[j] < blackclamp[0])
484                 Pos[j] = blackclamp[0];
485 
486             if (Pos[j] > 255 + whiteclamp[0])
487                 Pos[j] = 255 + whiteclamp[0];
488 
489             Pos[j] += Ref[j];
490         }
491     }
492 }
493 
494 /* Blend the macro block with a solid colored square.  Leave the
495  * edges unblended to give distinction to macro blocks in areas
496  * filled with the same color block.
497  */
vp8_blend_mb_inner_c(unsigned char * y,unsigned char * u,unsigned char * v,int y1,int u1,int v1,int alpha,int stride)498 void vp8_blend_mb_inner_c (unsigned char *y, unsigned char *u, unsigned char *v,
499                         int y1, int u1, int v1, int alpha, int stride)
500 {
501     int i, j;
502     int y1_const = y1*((1<<16)-alpha);
503     int u1_const = u1*((1<<16)-alpha);
504     int v1_const = v1*((1<<16)-alpha);
505 
506     y += 2*stride + 2;
507     for (i = 0; i < 12; i++)
508     {
509         for (j = 0; j < 12; j++)
510         {
511             y[j] = (y[j]*alpha + y1_const)>>16;
512         }
513         y += stride;
514     }
515 
516     stride >>= 1;
517 
518     u += stride + 1;
519     v += stride + 1;
520 
521     for (i = 0; i < 6; i++)
522     {
523         for (j = 0; j < 6; j++)
524         {
525             u[j] = (u[j]*alpha + u1_const)>>16;
526             v[j] = (v[j]*alpha + v1_const)>>16;
527         }
528         u += stride;
529         v += stride;
530     }
531 }
532 
533 /* Blend only the edge of the macro block.  Leave center
534  * unblended to allow for other visualizations to be layered.
535  */
vp8_blend_mb_outer_c(unsigned char * y,unsigned char * u,unsigned char * v,int y1,int u1,int v1,int alpha,int stride)536 void vp8_blend_mb_outer_c (unsigned char *y, unsigned char *u, unsigned char *v,
537                         int y1, int u1, int v1, int alpha, int stride)
538 {
539     int i, j;
540     int y1_const = y1*((1<<16)-alpha);
541     int u1_const = u1*((1<<16)-alpha);
542     int v1_const = v1*((1<<16)-alpha);
543 
544     for (i = 0; i < 2; i++)
545     {
546         for (j = 0; j < 16; j++)
547         {
548             y[j] = (y[j]*alpha + y1_const)>>16;
549         }
550         y += stride;
551     }
552 
553     for (i = 0; i < 12; i++)
554     {
555         y[0]  = (y[0]*alpha  + y1_const)>>16;
556         y[1]  = (y[1]*alpha  + y1_const)>>16;
557         y[14] = (y[14]*alpha + y1_const)>>16;
558         y[15] = (y[15]*alpha + y1_const)>>16;
559         y += stride;
560     }
561 
562     for (i = 0; i < 2; i++)
563     {
564         for (j = 0; j < 16; j++)
565         {
566             y[j] = (y[j]*alpha + y1_const)>>16;
567         }
568         y += stride;
569     }
570 
571     stride >>= 1;
572 
573     for (j = 0; j < 8; j++)
574     {
575         u[j] = (u[j]*alpha + u1_const)>>16;
576         v[j] = (v[j]*alpha + v1_const)>>16;
577     }
578     u += stride;
579     v += stride;
580 
581     for (i = 0; i < 6; i++)
582     {
583         u[0] = (u[0]*alpha + u1_const)>>16;
584         v[0] = (v[0]*alpha + v1_const)>>16;
585 
586         u[7] = (u[7]*alpha + u1_const)>>16;
587         v[7] = (v[7]*alpha + v1_const)>>16;
588 
589         u += stride;
590         v += stride;
591     }
592 
593     for (j = 0; j < 8; j++)
594     {
595         u[j] = (u[j]*alpha + u1_const)>>16;
596         v[j] = (v[j]*alpha + v1_const)>>16;
597     }
598 }
599 
vp8_blend_b_c(unsigned char * y,unsigned char * u,unsigned char * v,int y1,int u1,int v1,int alpha,int stride)600 void vp8_blend_b_c (unsigned char *y, unsigned char *u, unsigned char *v,
601                         int y1, int u1, int v1, int alpha, int stride)
602 {
603     int i, j;
604     int y1_const = y1*((1<<16)-alpha);
605     int u1_const = u1*((1<<16)-alpha);
606     int v1_const = v1*((1<<16)-alpha);
607 
608     for (i = 0; i < 4; i++)
609     {
610         for (j = 0; j < 4; j++)
611         {
612             y[j] = (y[j]*alpha + y1_const)>>16;
613         }
614         y += stride;
615     }
616 
617     stride >>= 1;
618 
619     for (i = 0; i < 2; i++)
620     {
621         for (j = 0; j < 2; j++)
622         {
623             u[j] = (u[j]*alpha + u1_const)>>16;
624             v[j] = (v[j]*alpha + v1_const)>>16;
625         }
626         u += stride;
627         v += stride;
628     }
629 }
630 
constrain_line(int x0,int * x1,int y0,int * y1,int width,int height)631 static void constrain_line (int x0, int *x1, int y0, int *y1, int width, int height)
632 {
633     int dx;
634     int dy;
635 
636     if (*x1 > width)
637     {
638         dx = *x1 - x0;
639         dy = *y1 - y0;
640 
641         *x1 = width;
642         if (dx)
643             *y1 = ((width-x0)*dy)/dx + y0;
644     }
645     if (*x1 < 0)
646     {
647         dx = *x1 - x0;
648         dy = *y1 - y0;
649 
650         *x1 = 0;
651         if (dx)
652             *y1 = ((0-x0)*dy)/dx + y0;
653     }
654     if (*y1 > height)
655     {
656         dx = *x1 - x0;
657         dy = *y1 - y0;
658 
659         *y1 = height;
660         if (dy)
661             *x1 = ((height-y0)*dx)/dy + x0;
662     }
663     if (*y1 < 0)
664     {
665         dx = *x1 - x0;
666         dy = *y1 - y0;
667 
668         *y1 = 0;
669         if (dy)
670             *x1 = ((0-y0)*dx)/dy + x0;
671     }
672 }
673 
674 
675 #if CONFIG_RUNTIME_CPU_DETECT
676 #define RTCD_VTABLE(oci) (&(oci)->rtcd.postproc)
677 #else
678 #define RTCD_VTABLE(oci) NULL
679 #endif
680 
vp8_post_proc_frame(VP8_COMMON * oci,YV12_BUFFER_CONFIG * dest,vp8_ppflags_t * ppflags)681 int vp8_post_proc_frame(VP8_COMMON *oci, YV12_BUFFER_CONFIG *dest, vp8_ppflags_t *ppflags)
682 {
683     int q = oci->filter_level * 10 / 6;
684     int flags = ppflags->post_proc_flag;
685     int deblock_level = ppflags->deblocking_level;
686     int noise_level = ppflags->noise_level;
687 
688     if (!oci->frame_to_show)
689         return -1;
690 
691     if (q > 63)
692         q = 63;
693 
694     if (!flags)
695     {
696         *dest = *oci->frame_to_show;
697 
698         /* handle problem with extending borders */
699         dest->y_width = oci->Width;
700         dest->y_height = oci->Height;
701         dest->uv_height = dest->y_height / 2;
702         return 0;
703 
704     }
705 
706 #if ARCH_X86||ARCH_X86_64
707     vpx_reset_mmx_state();
708 #endif
709 
710     if (flags & VP8D_DEMACROBLOCK)
711     {
712         vp8_deblock_and_de_macro_block(oci->frame_to_show, &oci->post_proc_buffer,
713                                        q + (deblock_level - 5) * 10, 1, 0, RTCD_VTABLE(oci));
714     }
715     else if (flags & VP8D_DEBLOCK)
716     {
717         vp8_deblock(oci->frame_to_show, &oci->post_proc_buffer,
718                     q, 1, 0, RTCD_VTABLE(oci));
719     }
720     else
721     {
722         vp8_yv12_copy_frame_ptr(oci->frame_to_show, &oci->post_proc_buffer);
723     }
724 
725     if (flags & VP8D_ADDNOISE)
726     {
727         if (oci->postproc_state.last_q != q
728             || oci->postproc_state.last_noise != noise_level)
729         {
730             fillrd(&oci->postproc_state, 63 - q, noise_level);
731         }
732 
733         POSTPROC_INVOKE(RTCD_VTABLE(oci), addnoise)
734         (oci->post_proc_buffer.y_buffer,
735          oci->postproc_state.noise,
736          oci->postproc_state.blackclamp,
737          oci->postproc_state.whiteclamp,
738          oci->postproc_state.bothclamp,
739          oci->post_proc_buffer.y_width, oci->post_proc_buffer.y_height,
740          oci->post_proc_buffer.y_stride);
741     }
742 
743 #if CONFIG_POSTPROC_VISUALIZER
744     if (flags & VP8D_DEBUG_TXT_FRAME_INFO)
745     {
746         char message[512];
747         sprintf(message, "F%1dG%1dQ%3dF%3dP%d_s%dx%d",
748                 (oci->frame_type == KEY_FRAME),
749                 oci->refresh_golden_frame,
750                 oci->base_qindex,
751                 oci->filter_level,
752                 flags,
753                 oci->mb_cols, oci->mb_rows);
754         vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
755     }
756 
757     if (flags & VP8D_DEBUG_TXT_MBLK_MODES)
758     {
759         int i, j;
760         unsigned char *y_ptr;
761         YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
762         int mb_rows = post->y_height >> 4;
763         int mb_cols = post->y_width  >> 4;
764         int mb_index = 0;
765         MODE_INFO *mi = oci->mi;
766 
767         y_ptr = post->y_buffer + 4 * post->y_stride + 4;
768 
769         /* vp8_filter each macro block */
770         for (i = 0; i < mb_rows; i++)
771         {
772             for (j = 0; j < mb_cols; j++)
773             {
774                 char zz[4];
775 
776                 sprintf(zz, "%c", mi[mb_index].mbmi.mode + 'a');
777 
778                 vp8_blit_text(zz, y_ptr, post->y_stride);
779                 mb_index ++;
780                 y_ptr += 16;
781             }
782 
783             mb_index ++; /* border */
784             y_ptr += post->y_stride  * 16 - post->y_width;
785 
786         }
787     }
788 
789     if (flags & VP8D_DEBUG_TXT_DC_DIFF)
790     {
791         int i, j;
792         unsigned char *y_ptr;
793         YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
794         int mb_rows = post->y_height >> 4;
795         int mb_cols = post->y_width  >> 4;
796         int mb_index = 0;
797         MODE_INFO *mi = oci->mi;
798 
799         y_ptr = post->y_buffer + 4 * post->y_stride + 4;
800 
801         /* vp8_filter each macro block */
802         for (i = 0; i < mb_rows; i++)
803         {
804             for (j = 0; j < mb_cols; j++)
805             {
806                 char zz[4];
807 
808                 if (oci->frame_type == KEY_FRAME)
809                     sprintf(zz, "a");
810                 else
811                     sprintf(zz, "%c", mi[mb_index].mbmi.dc_diff + '0');
812 
813                 vp8_blit_text(zz, y_ptr, post->y_stride);
814                 mb_index ++;
815                 y_ptr += 16;
816             }
817 
818             mb_index ++; /* border */
819             y_ptr += post->y_stride  * 16 - post->y_width;
820 
821         }
822     }
823 
824     if (flags & VP8D_DEBUG_TXT_RATE_INFO)
825     {
826         char message[512];
827         sprintf(message, "Bitrate: %10.2f frame_rate: %10.2f ", oci->bitrate, oci->framerate);
828         vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
829     }
830 
831     /* Draw motion vectors */
832     if ((flags & VP8D_DEBUG_DRAW_MV) && ppflags->display_mv_flag)
833     {
834         YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
835         int width  = post->y_width;
836         int height = post->y_height;
837         int mb_cols = width  >> 4;
838         unsigned char *y_buffer = oci->post_proc_buffer.y_buffer;
839         int y_stride = oci->post_proc_buffer.y_stride;
840         MODE_INFO *mi = oci->mi;
841         int x0, y0;
842 
843         for (y0 = 0; y0 < height; y0 += 16)
844         {
845             for (x0 = 0; x0 < width; x0 += 16)
846             {
847                 int x1, y1;
848 
849                 if (!(ppflags->display_mv_flag & (1<<mi->mbmi.mode)))
850                 {
851                     mi++;
852                     continue;
853                 }
854 
855                 if (mi->mbmi.mode == SPLITMV)
856                 {
857                     switch (mi->mbmi.partitioning)
858                     {
859                         case 0 :    /* mv_top_bottom */
860                         {
861                             B_MODE_INFO *bmi = &mi->bmi[0];
862                             MV *mv = &bmi->mv.as_mv;
863 
864                             x1 = x0 + 8 + (mv->col >> 3);
865                             y1 = y0 + 4 + (mv->row >> 3);
866 
867                             constrain_line (x0+8, &x1, y0+4, &y1, width, height);
868                             vp8_blit_line  (x0+8,  x1, y0+4,  y1, y_buffer, y_stride);
869 
870                             bmi = &mi->bmi[8];
871 
872                             x1 = x0 + 8 + (mv->col >> 3);
873                             y1 = y0 +12 + (mv->row >> 3);
874 
875                             constrain_line (x0+8, &x1, y0+12, &y1, width, height);
876                             vp8_blit_line  (x0+8,  x1, y0+12,  y1, y_buffer, y_stride);
877 
878                             break;
879                         }
880                         case 1 :    /* mv_left_right */
881                         {
882                             B_MODE_INFO *bmi = &mi->bmi[0];
883                             MV *mv = &bmi->mv.as_mv;
884 
885                             x1 = x0 + 4 + (mv->col >> 3);
886                             y1 = y0 + 8 + (mv->row >> 3);
887 
888                             constrain_line (x0+4, &x1, y0+8, &y1, width, height);
889                             vp8_blit_line  (x0+4,  x1, y0+8,  y1, y_buffer, y_stride);
890 
891                             bmi = &mi->bmi[2];
892 
893                             x1 = x0 +12 + (mv->col >> 3);
894                             y1 = y0 + 8 + (mv->row >> 3);
895 
896                             constrain_line (x0+12, &x1, y0+8, &y1, width, height);
897                             vp8_blit_line  (x0+12,  x1, y0+8,  y1, y_buffer, y_stride);
898 
899                             break;
900                         }
901                         case 2 :    /* mv_quarters   */
902                         {
903                             B_MODE_INFO *bmi = &mi->bmi[0];
904                             MV *mv = &bmi->mv.as_mv;
905 
906                             x1 = x0 + 4 + (mv->col >> 3);
907                             y1 = y0 + 4 + (mv->row >> 3);
908 
909                             constrain_line (x0+4, &x1, y0+4, &y1, width, height);
910                             vp8_blit_line  (x0+4,  x1, y0+4,  y1, y_buffer, y_stride);
911 
912                             bmi = &mi->bmi[2];
913 
914                             x1 = x0 +12 + (mv->col >> 3);
915                             y1 = y0 + 4 + (mv->row >> 3);
916 
917                             constrain_line (x0+12, &x1, y0+4, &y1, width, height);
918                             vp8_blit_line  (x0+12,  x1, y0+4,  y1, y_buffer, y_stride);
919 
920                             bmi = &mi->bmi[8];
921 
922                             x1 = x0 + 4 + (mv->col >> 3);
923                             y1 = y0 +12 + (mv->row >> 3);
924 
925                             constrain_line (x0+4, &x1, y0+12, &y1, width, height);
926                             vp8_blit_line  (x0+4,  x1, y0+12,  y1, y_buffer, y_stride);
927 
928                             bmi = &mi->bmi[10];
929 
930                             x1 = x0 +12 + (mv->col >> 3);
931                             y1 = y0 +12 + (mv->row >> 3);
932 
933                             constrain_line (x0+12, &x1, y0+12, &y1, width, height);
934                             vp8_blit_line  (x0+12,  x1, y0+12,  y1, y_buffer, y_stride);
935                             break;
936                         }
937                         default :
938                         {
939                             B_MODE_INFO *bmi = mi->bmi;
940                             int bx0, by0;
941 
942                             for (by0 = y0; by0 < (y0+16); by0 += 4)
943                             {
944                                 for (bx0 = x0; bx0 < (x0+16); bx0 += 4)
945                                 {
946                                     MV *mv = &bmi->mv.as_mv;
947 
948                                     x1 = bx0 + 2 + (mv->col >> 3);
949                                     y1 = by0 + 2 + (mv->row >> 3);
950 
951                                     constrain_line (bx0+2, &x1, by0+2, &y1, width, height);
952                                     vp8_blit_line  (bx0+2,  x1, by0+2,  y1, y_buffer, y_stride);
953 
954                                     bmi++;
955                                 }
956                             }
957                         }
958                     }
959                 }
960                 else if (mi->mbmi.mode >= NEARESTMV)
961                 {
962                     MV *mv = &mi->mbmi.mv.as_mv;
963                     const int lx0 = x0 + 8;
964                     const int ly0 = y0 + 8;
965 
966                     x1 = lx0 + (mv->col >> 3);
967                     y1 = ly0 + (mv->row >> 3);
968 
969                     if (x1 != lx0 && y1 != ly0)
970                     {
971                         constrain_line (lx0, &x1, ly0-1, &y1, width, height);
972                         vp8_blit_line  (lx0,  x1, ly0-1,  y1, y_buffer, y_stride);
973 
974                         constrain_line (lx0, &x1, ly0+1, &y1, width, height);
975                         vp8_blit_line  (lx0,  x1, ly0+1,  y1, y_buffer, y_stride);
976                     }
977                     else
978                         vp8_blit_line  (lx0,  x1, ly0,  y1, y_buffer, y_stride);
979                 }
980 
981                 mi++;
982             }
983             mi++;
984         }
985     }
986 
987     /* Color in block modes */
988     if ((flags & VP8D_DEBUG_CLR_BLK_MODES)
989         && (ppflags->display_mb_modes_flag || ppflags->display_b_modes_flag))
990     {
991         int y, x;
992         YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
993         int width  = post->y_width;
994         int height = post->y_height;
995         unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
996         unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
997         unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
998         int y_stride = oci->post_proc_buffer.y_stride;
999         MODE_INFO *mi = oci->mi;
1000 
1001         for (y = 0; y < height; y += 16)
1002         {
1003             for (x = 0; x < width; x += 16)
1004             {
1005                 int Y = 0, U = 0, V = 0;
1006 
1007                 if (mi->mbmi.mode == B_PRED &&
1008                     ((ppflags->display_mb_modes_flag & B_PRED) || ppflags->display_b_modes_flag))
1009                 {
1010                     int by, bx;
1011                     unsigned char *yl, *ul, *vl;
1012                     B_MODE_INFO *bmi = mi->bmi;
1013 
1014                     yl = y_ptr + x;
1015                     ul = u_ptr + (x>>1);
1016                     vl = v_ptr + (x>>1);
1017 
1018                     for (by = 0; by < 16; by += 4)
1019                     {
1020                         for (bx = 0; bx < 16; bx += 4)
1021                         {
1022                             if ((ppflags->display_b_modes_flag & (1<<mi->mbmi.mode))
1023                                 || (ppflags->display_mb_modes_flag & B_PRED))
1024                             {
1025                                 Y = B_PREDICTION_MODE_colors[bmi->mode][0];
1026                                 U = B_PREDICTION_MODE_colors[bmi->mode][1];
1027                                 V = B_PREDICTION_MODE_colors[bmi->mode][2];
1028 
1029                                 POSTPROC_INVOKE(RTCD_VTABLE(oci), blend_b)
1030                                     (yl+bx, ul+(bx>>1), vl+(bx>>1), Y, U, V, 0xc000, y_stride);
1031                             }
1032                             bmi++;
1033                         }
1034 
1035                         yl += y_stride*4;
1036                         ul += y_stride*1;
1037                         vl += y_stride*1;
1038                     }
1039                 }
1040                 else if (ppflags->display_mb_modes_flag & (1<<mi->mbmi.mode))
1041                 {
1042                     Y = MB_PREDICTION_MODE_colors[mi->mbmi.mode][0];
1043                     U = MB_PREDICTION_MODE_colors[mi->mbmi.mode][1];
1044                     V = MB_PREDICTION_MODE_colors[mi->mbmi.mode][2];
1045 
1046                     POSTPROC_INVOKE(RTCD_VTABLE(oci), blend_mb_inner)
1047                         (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1048                 }
1049 
1050                 mi++;
1051             }
1052             y_ptr += y_stride*16;
1053             u_ptr += y_stride*4;
1054             v_ptr += y_stride*4;
1055 
1056             mi++;
1057         }
1058     }
1059 
1060     /* Color in frame reference blocks */
1061     if ((flags & VP8D_DEBUG_CLR_FRM_REF_BLKS) && ppflags->display_ref_frame_flag)
1062     {
1063         int y, x;
1064         YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
1065         int width  = post->y_width;
1066         int height = post->y_height;
1067         unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
1068         unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
1069         unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
1070         int y_stride = oci->post_proc_buffer.y_stride;
1071         MODE_INFO *mi = oci->mi;
1072 
1073         for (y = 0; y < height; y += 16)
1074         {
1075             for (x = 0; x < width; x +=16)
1076             {
1077                 int Y = 0, U = 0, V = 0;
1078 
1079                 if (ppflags->display_ref_frame_flag & (1<<mi->mbmi.ref_frame))
1080                 {
1081                     Y = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][0];
1082                     U = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][1];
1083                     V = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][2];
1084 
1085                     POSTPROC_INVOKE(RTCD_VTABLE(oci), blend_mb_outer)
1086                         (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1087                 }
1088 
1089                 mi++;
1090             }
1091             y_ptr += y_stride*16;
1092             u_ptr += y_stride*4;
1093             v_ptr += y_stride*4;
1094 
1095             mi++;
1096         }
1097     }
1098 #endif
1099 
1100     *dest = oci->post_proc_buffer;
1101 
1102     /* handle problem with extending borders */
1103     dest->y_width = oci->Width;
1104     dest->y_height = oci->Height;
1105     dest->uv_height = dest->y_height / 2;
1106     return 0;
1107 }
1108