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