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