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
constrain_line(int x_0,int * x_1,int y_0,int * y_1,int width,int height)678 static void constrain_line (int x_0, int *x_1, int y_0, int *y_1, int width, int height)
679 {
680 int dx;
681 int dy;
682
683 if (*x_1 > width)
684 {
685 dx = *x_1 - x_0;
686 dy = *y_1 - y_0;
687
688 *x_1 = width;
689 if (dx)
690 *y_1 = ((width-x_0)*dy)/dx + y_0;
691 }
692 if (*x_1 < 0)
693 {
694 dx = *x_1 - x_0;
695 dy = *y_1 - y_0;
696
697 *x_1 = 0;
698 if (dx)
699 *y_1 = ((0-x_0)*dy)/dx + y_0;
700 }
701 if (*y_1 > height)
702 {
703 dx = *x_1 - x_0;
704 dy = *y_1 - y_0;
705
706 *y_1 = height;
707 if (dy)
708 *x_1 = ((height-y_0)*dx)/dy + x_0;
709 }
710 if (*y_1 < 0)
711 {
712 dx = *x_1 - x_0;
713 dy = *y_1 - y_0;
714
715 *y_1 = 0;
716 if (dy)
717 *x_1 = ((0-y_0)*dx)/dy + x_0;
718 }
719 }
720
721 #if CONFIG_POSTPROC
vp8_post_proc_frame(VP8_COMMON * oci,YV12_BUFFER_CONFIG * dest,vp8_ppflags_t * ppflags)722 int vp8_post_proc_frame(VP8_COMMON *oci, YV12_BUFFER_CONFIG *dest, vp8_ppflags_t *ppflags)
723 {
724 int q = oci->filter_level * 10 / 6;
725 int flags = ppflags->post_proc_flag;
726 int deblock_level = ppflags->deblocking_level;
727 int noise_level = ppflags->noise_level;
728
729 if (!oci->frame_to_show)
730 return -1;
731
732 if (q > 63)
733 q = 63;
734
735 if (!flags)
736 {
737 *dest = *oci->frame_to_show;
738
739 /* handle problem with extending borders */
740 dest->y_width = oci->Width;
741 dest->y_height = oci->Height;
742 dest->uv_height = dest->y_height / 2;
743 oci->postproc_state.last_base_qindex = oci->base_qindex;
744 oci->postproc_state.last_frame_valid = 1;
745 return 0;
746 }
747
748 /* Allocate post_proc_buffer_int if needed */
749 if ((flags & VP8D_MFQE) && !oci->post_proc_buffer_int_used)
750 {
751 if ((flags & VP8D_DEBLOCK) || (flags & VP8D_DEMACROBLOCK))
752 {
753 int width = (oci->Width + 15) & ~15;
754 int height = (oci->Height + 15) & ~15;
755
756 if (vp8_yv12_alloc_frame_buffer(&oci->post_proc_buffer_int,
757 width, height, VP8BORDERINPIXELS))
758 vpx_internal_error(&oci->error, VPX_CODEC_MEM_ERROR,
759 "Failed to allocate MFQE framebuffer");
760
761 oci->post_proc_buffer_int_used = 1;
762
763 /* insure that postproc is set to all 0's so that post proc
764 * doesn't pull random data in from edge
765 */
766 memset((&oci->post_proc_buffer_int)->buffer_alloc,128,(&oci->post_proc_buffer)->frame_size);
767
768 }
769 }
770
771 vp8_clear_system_state();
772
773 if ((flags & VP8D_MFQE) &&
774 oci->postproc_state.last_frame_valid &&
775 oci->current_video_frame >= 2 &&
776 oci->postproc_state.last_base_qindex < 60 &&
777 oci->base_qindex - oci->postproc_state.last_base_qindex >= 20)
778 {
779 vp8_multiframe_quality_enhance(oci);
780 if (((flags & VP8D_DEBLOCK) || (flags & VP8D_DEMACROBLOCK)) &&
781 oci->post_proc_buffer_int_used)
782 {
783 vp8_yv12_copy_frame(&oci->post_proc_buffer, &oci->post_proc_buffer_int);
784 if (flags & VP8D_DEMACROBLOCK)
785 {
786 vp8_deblock(oci, &oci->post_proc_buffer_int, &oci->post_proc_buffer,
787 q + (deblock_level - 5) * 10, 1, 0);
788 vp8_de_mblock(&oci->post_proc_buffer,
789 q + (deblock_level - 5) * 10);
790 }
791 else if (flags & VP8D_DEBLOCK)
792 {
793 vp8_deblock(oci, &oci->post_proc_buffer_int, &oci->post_proc_buffer,
794 q, 1, 0);
795 }
796 }
797 /* Move partially towards the base q of the previous frame */
798 oci->postproc_state.last_base_qindex = (3*oci->postproc_state.last_base_qindex + oci->base_qindex)>>2;
799 }
800 else if (flags & VP8D_DEMACROBLOCK)
801 {
802 vp8_deblock(oci, oci->frame_to_show, &oci->post_proc_buffer,
803 q + (deblock_level - 5) * 10, 1, 0);
804 vp8_de_mblock(&oci->post_proc_buffer, q + (deblock_level - 5) * 10);
805
806 oci->postproc_state.last_base_qindex = oci->base_qindex;
807 }
808 else if (flags & VP8D_DEBLOCK)
809 {
810 vp8_deblock(oci, oci->frame_to_show, &oci->post_proc_buffer,
811 q, 1, 0);
812 oci->postproc_state.last_base_qindex = oci->base_qindex;
813 }
814 else
815 {
816 vp8_yv12_copy_frame(oci->frame_to_show, &oci->post_proc_buffer);
817 oci->postproc_state.last_base_qindex = oci->base_qindex;
818 }
819 oci->postproc_state.last_frame_valid = 1;
820
821 if (flags & VP8D_ADDNOISE)
822 {
823 if (oci->postproc_state.last_q != q
824 || oci->postproc_state.last_noise != noise_level)
825 {
826 fillrd(&oci->postproc_state, 63 - q, noise_level);
827 }
828
829 vp8_plane_add_noise
830 (oci->post_proc_buffer.y_buffer,
831 oci->postproc_state.noise,
832 oci->postproc_state.blackclamp,
833 oci->postproc_state.whiteclamp,
834 oci->postproc_state.bothclamp,
835 oci->post_proc_buffer.y_width, oci->post_proc_buffer.y_height,
836 oci->post_proc_buffer.y_stride);
837 }
838
839 #if CONFIG_POSTPROC_VISUALIZER
840 if (flags & VP8D_DEBUG_TXT_FRAME_INFO)
841 {
842 char message[512];
843 sprintf(message, "F%1dG%1dQ%3dF%3dP%d_s%dx%d",
844 (oci->frame_type == KEY_FRAME),
845 oci->refresh_golden_frame,
846 oci->base_qindex,
847 oci->filter_level,
848 flags,
849 oci->mb_cols, oci->mb_rows);
850 vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
851 }
852
853 if (flags & VP8D_DEBUG_TXT_MBLK_MODES)
854 {
855 int i, j;
856 unsigned char *y_ptr;
857 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
858 int mb_rows = post->y_height >> 4;
859 int mb_cols = post->y_width >> 4;
860 int mb_index = 0;
861 MODE_INFO *mi = oci->mi;
862
863 y_ptr = post->y_buffer + 4 * post->y_stride + 4;
864
865 /* vp8_filter each macro block */
866 for (i = 0; i < mb_rows; i++)
867 {
868 for (j = 0; j < mb_cols; j++)
869 {
870 char zz[4];
871
872 sprintf(zz, "%c", mi[mb_index].mbmi.mode + 'a');
873
874 vp8_blit_text(zz, y_ptr, post->y_stride);
875 mb_index ++;
876 y_ptr += 16;
877 }
878
879 mb_index ++; /* border */
880 y_ptr += post->y_stride * 16 - post->y_width;
881
882 }
883 }
884
885 if (flags & VP8D_DEBUG_TXT_DC_DIFF)
886 {
887 int i, j;
888 unsigned char *y_ptr;
889 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
890 int mb_rows = post->y_height >> 4;
891 int mb_cols = post->y_width >> 4;
892 int mb_index = 0;
893 MODE_INFO *mi = oci->mi;
894
895 y_ptr = post->y_buffer + 4 * post->y_stride + 4;
896
897 /* vp8_filter each macro block */
898 for (i = 0; i < mb_rows; i++)
899 {
900 for (j = 0; j < mb_cols; j++)
901 {
902 char zz[4];
903 int dc_diff = !(mi[mb_index].mbmi.mode != B_PRED &&
904 mi[mb_index].mbmi.mode != SPLITMV &&
905 mi[mb_index].mbmi.mb_skip_coeff);
906
907 if (oci->frame_type == KEY_FRAME)
908 sprintf(zz, "a");
909 else
910 sprintf(zz, "%c", dc_diff + '0');
911
912 vp8_blit_text(zz, y_ptr, post->y_stride);
913 mb_index ++;
914 y_ptr += 16;
915 }
916
917 mb_index ++; /* border */
918 y_ptr += post->y_stride * 16 - post->y_width;
919
920 }
921 }
922
923 if (flags & VP8D_DEBUG_TXT_RATE_INFO)
924 {
925 char message[512];
926 sprintf(message, "Bitrate: %10.2f framerate: %10.2f ", oci->bitrate, oci->framerate);
927 vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
928 }
929
930 /* Draw motion vectors */
931 if ((flags & VP8D_DEBUG_DRAW_MV) && ppflags->display_mv_flag)
932 {
933 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
934 int width = post->y_width;
935 int height = post->y_height;
936 unsigned char *y_buffer = oci->post_proc_buffer.y_buffer;
937 int y_stride = oci->post_proc_buffer.y_stride;
938 MODE_INFO *mi = oci->mi;
939 int x0, y0;
940
941 for (y0 = 0; y0 < height; y0 += 16)
942 {
943 for (x0 = 0; x0 < width; x0 += 16)
944 {
945 int x1, y1;
946
947 if (!(ppflags->display_mv_flag & (1<<mi->mbmi.mode)))
948 {
949 mi++;
950 continue;
951 }
952
953 if (mi->mbmi.mode == SPLITMV)
954 {
955 switch (mi->mbmi.partitioning)
956 {
957 case 0 : /* mv_top_bottom */
958 {
959 union b_mode_info *bmi = &mi->bmi[0];
960 MV *mv = &bmi->mv.as_mv;
961
962 x1 = x0 + 8 + (mv->col >> 3);
963 y1 = y0 + 4 + (mv->row >> 3);
964
965 constrain_line (x0+8, &x1, y0+4, &y1, width, height);
966 vp8_blit_line (x0+8, x1, y0+4, y1, y_buffer, y_stride);
967
968 bmi = &mi->bmi[8];
969
970 x1 = x0 + 8 + (mv->col >> 3);
971 y1 = y0 +12 + (mv->row >> 3);
972
973 constrain_line (x0+8, &x1, y0+12, &y1, width, height);
974 vp8_blit_line (x0+8, x1, y0+12, y1, y_buffer, y_stride);
975
976 break;
977 }
978 case 1 : /* mv_left_right */
979 {
980 union b_mode_info *bmi = &mi->bmi[0];
981 MV *mv = &bmi->mv.as_mv;
982
983 x1 = x0 + 4 + (mv->col >> 3);
984 y1 = y0 + 8 + (mv->row >> 3);
985
986 constrain_line (x0+4, &x1, y0+8, &y1, width, height);
987 vp8_blit_line (x0+4, x1, y0+8, y1, y_buffer, y_stride);
988
989 bmi = &mi->bmi[2];
990
991 x1 = x0 +12 + (mv->col >> 3);
992 y1 = y0 + 8 + (mv->row >> 3);
993
994 constrain_line (x0+12, &x1, y0+8, &y1, width, height);
995 vp8_blit_line (x0+12, x1, y0+8, y1, y_buffer, y_stride);
996
997 break;
998 }
999 case 2 : /* mv_quarters */
1000 {
1001 union b_mode_info *bmi = &mi->bmi[0];
1002 MV *mv = &bmi->mv.as_mv;
1003
1004 x1 = x0 + 4 + (mv->col >> 3);
1005 y1 = y0 + 4 + (mv->row >> 3);
1006
1007 constrain_line (x0+4, &x1, y0+4, &y1, width, height);
1008 vp8_blit_line (x0+4, x1, y0+4, y1, y_buffer, y_stride);
1009
1010 bmi = &mi->bmi[2];
1011
1012 x1 = x0 +12 + (mv->col >> 3);
1013 y1 = y0 + 4 + (mv->row >> 3);
1014
1015 constrain_line (x0+12, &x1, y0+4, &y1, width, height);
1016 vp8_blit_line (x0+12, x1, y0+4, y1, y_buffer, y_stride);
1017
1018 bmi = &mi->bmi[8];
1019
1020 x1 = x0 + 4 + (mv->col >> 3);
1021 y1 = y0 +12 + (mv->row >> 3);
1022
1023 constrain_line (x0+4, &x1, y0+12, &y1, width, height);
1024 vp8_blit_line (x0+4, x1, y0+12, y1, y_buffer, y_stride);
1025
1026 bmi = &mi->bmi[10];
1027
1028 x1 = x0 +12 + (mv->col >> 3);
1029 y1 = y0 +12 + (mv->row >> 3);
1030
1031 constrain_line (x0+12, &x1, y0+12, &y1, width, height);
1032 vp8_blit_line (x0+12, x1, y0+12, y1, y_buffer, y_stride);
1033 break;
1034 }
1035 default :
1036 {
1037 union b_mode_info *bmi = mi->bmi;
1038 int bx0, by0;
1039
1040 for (by0 = y0; by0 < (y0+16); by0 += 4)
1041 {
1042 for (bx0 = x0; bx0 < (x0+16); bx0 += 4)
1043 {
1044 MV *mv = &bmi->mv.as_mv;
1045
1046 x1 = bx0 + 2 + (mv->col >> 3);
1047 y1 = by0 + 2 + (mv->row >> 3);
1048
1049 constrain_line (bx0+2, &x1, by0+2, &y1, width, height);
1050 vp8_blit_line (bx0+2, x1, by0+2, y1, y_buffer, y_stride);
1051
1052 bmi++;
1053 }
1054 }
1055 }
1056 }
1057 }
1058 else if (mi->mbmi.mode >= NEARESTMV)
1059 {
1060 MV *mv = &mi->mbmi.mv.as_mv;
1061 const int lx0 = x0 + 8;
1062 const int ly0 = y0 + 8;
1063
1064 x1 = lx0 + (mv->col >> 3);
1065 y1 = ly0 + (mv->row >> 3);
1066
1067 if (x1 != lx0 && y1 != ly0)
1068 {
1069 constrain_line (lx0, &x1, ly0-1, &y1, width, height);
1070 vp8_blit_line (lx0, x1, ly0-1, y1, y_buffer, y_stride);
1071
1072 constrain_line (lx0, &x1, ly0+1, &y1, width, height);
1073 vp8_blit_line (lx0, x1, ly0+1, y1, y_buffer, y_stride);
1074 }
1075 else
1076 vp8_blit_line (lx0, x1, ly0, y1, y_buffer, y_stride);
1077 }
1078
1079 mi++;
1080 }
1081 mi++;
1082 }
1083 }
1084
1085 /* Color in block modes */
1086 if ((flags & VP8D_DEBUG_CLR_BLK_MODES)
1087 && (ppflags->display_mb_modes_flag || ppflags->display_b_modes_flag))
1088 {
1089 int y, x;
1090 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
1091 int width = post->y_width;
1092 int height = post->y_height;
1093 unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
1094 unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
1095 unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
1096 int y_stride = oci->post_proc_buffer.y_stride;
1097 MODE_INFO *mi = oci->mi;
1098
1099 for (y = 0; y < height; y += 16)
1100 {
1101 for (x = 0; x < width; x += 16)
1102 {
1103 int Y = 0, U = 0, V = 0;
1104
1105 if (mi->mbmi.mode == B_PRED &&
1106 ((ppflags->display_mb_modes_flag & B_PRED) || ppflags->display_b_modes_flag))
1107 {
1108 int by, bx;
1109 unsigned char *yl, *ul, *vl;
1110 union b_mode_info *bmi = mi->bmi;
1111
1112 yl = y_ptr + x;
1113 ul = u_ptr + (x>>1);
1114 vl = v_ptr + (x>>1);
1115
1116 for (by = 0; by < 16; by += 4)
1117 {
1118 for (bx = 0; bx < 16; bx += 4)
1119 {
1120 if ((ppflags->display_b_modes_flag & (1<<mi->mbmi.mode))
1121 || (ppflags->display_mb_modes_flag & B_PRED))
1122 {
1123 Y = B_PREDICTION_MODE_colors[bmi->as_mode][0];
1124 U = B_PREDICTION_MODE_colors[bmi->as_mode][1];
1125 V = B_PREDICTION_MODE_colors[bmi->as_mode][2];
1126
1127 vp8_blend_b
1128 (yl+bx, ul+(bx>>1), vl+(bx>>1), Y, U, V, 0xc000, y_stride);
1129 }
1130 bmi++;
1131 }
1132
1133 yl += y_stride*4;
1134 ul += y_stride*1;
1135 vl += y_stride*1;
1136 }
1137 }
1138 else if (ppflags->display_mb_modes_flag & (1<<mi->mbmi.mode))
1139 {
1140 Y = MB_PREDICTION_MODE_colors[mi->mbmi.mode][0];
1141 U = MB_PREDICTION_MODE_colors[mi->mbmi.mode][1];
1142 V = MB_PREDICTION_MODE_colors[mi->mbmi.mode][2];
1143
1144 vp8_blend_mb_inner
1145 (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1146 }
1147
1148 mi++;
1149 }
1150 y_ptr += y_stride*16;
1151 u_ptr += y_stride*4;
1152 v_ptr += y_stride*4;
1153
1154 mi++;
1155 }
1156 }
1157
1158 /* Color in frame reference blocks */
1159 if ((flags & VP8D_DEBUG_CLR_FRM_REF_BLKS) && ppflags->display_ref_frame_flag)
1160 {
1161 int y, x;
1162 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
1163 int width = post->y_width;
1164 int height = post->y_height;
1165 unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
1166 unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
1167 unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
1168 int y_stride = oci->post_proc_buffer.y_stride;
1169 MODE_INFO *mi = oci->mi;
1170
1171 for (y = 0; y < height; y += 16)
1172 {
1173 for (x = 0; x < width; x +=16)
1174 {
1175 int Y = 0, U = 0, V = 0;
1176
1177 if (ppflags->display_ref_frame_flag & (1<<mi->mbmi.ref_frame))
1178 {
1179 Y = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][0];
1180 U = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][1];
1181 V = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][2];
1182
1183 vp8_blend_mb_outer
1184 (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1185 }
1186
1187 mi++;
1188 }
1189 y_ptr += y_stride*16;
1190 u_ptr += y_stride*4;
1191 v_ptr += y_stride*4;
1192
1193 mi++;
1194 }
1195 }
1196 #endif
1197
1198 *dest = oci->post_proc_buffer;
1199
1200 /* handle problem with extending borders */
1201 dest->y_width = oci->Width;
1202 dest->y_height = oci->Height;
1203 dest->uv_height = dest->y_height / 2;
1204 return 0;
1205 }
1206 #endif
1207