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