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 vpx_memset(ylptr, mb_ppl, 16);
359 vpx_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 vpx_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
vp8_gaussian(double sigma,double mu,double x)430 double vp8_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 * vp8_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
522 for (i = 0; i < Height; i++)
523 {
524 unsigned char *Pos = Start + i * Pitch;
525 char *Ref = (char *)(noise + (rand() & 0xff));
526
527 for (j = 0; j < Width; j++)
528 {
529 if (Pos[j] < blackclamp[0])
530 Pos[j] = blackclamp[0];
531
532 if (Pos[j] > 255 + whiteclamp[0])
533 Pos[j] = 255 + whiteclamp[0];
534
535 Pos[j] += Ref[j];
536 }
537 }
538 }
539
540 /* Blend the macro block with a solid colored square. Leave the
541 * edges unblended to give distinction to macro blocks in areas
542 * filled with the same color block.
543 */
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)544 void vp8_blend_mb_inner_c (unsigned char *y, unsigned char *u, unsigned char *v,
545 int y_1, int u_1, int v_1, int alpha, int stride)
546 {
547 int i, j;
548 int y1_const = y_1*((1<<16)-alpha);
549 int u1_const = u_1*((1<<16)-alpha);
550 int v1_const = v_1*((1<<16)-alpha);
551
552 y += 2*stride + 2;
553 for (i = 0; i < 12; i++)
554 {
555 for (j = 0; j < 12; j++)
556 {
557 y[j] = (y[j]*alpha + y1_const)>>16;
558 }
559 y += stride;
560 }
561
562 stride >>= 1;
563
564 u += stride + 1;
565 v += stride + 1;
566
567 for (i = 0; i < 6; i++)
568 {
569 for (j = 0; j < 6; j++)
570 {
571 u[j] = (u[j]*alpha + u1_const)>>16;
572 v[j] = (v[j]*alpha + v1_const)>>16;
573 }
574 u += stride;
575 v += stride;
576 }
577 }
578
579 /* Blend only the edge of the macro block. Leave center
580 * unblended to allow for other visualizations to be layered.
581 */
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)582 void vp8_blend_mb_outer_c (unsigned char *y, unsigned char *u, unsigned char *v,
583 int y_1, int u_1, int v_1, int alpha, int stride)
584 {
585 int i, j;
586 int y1_const = y_1*((1<<16)-alpha);
587 int u1_const = u_1*((1<<16)-alpha);
588 int v1_const = v_1*((1<<16)-alpha);
589
590 for (i = 0; i < 2; i++)
591 {
592 for (j = 0; j < 16; j++)
593 {
594 y[j] = (y[j]*alpha + y1_const)>>16;
595 }
596 y += stride;
597 }
598
599 for (i = 0; i < 12; i++)
600 {
601 y[0] = (y[0]*alpha + y1_const)>>16;
602 y[1] = (y[1]*alpha + y1_const)>>16;
603 y[14] = (y[14]*alpha + y1_const)>>16;
604 y[15] = (y[15]*alpha + y1_const)>>16;
605 y += stride;
606 }
607
608 for (i = 0; i < 2; i++)
609 {
610 for (j = 0; j < 16; j++)
611 {
612 y[j] = (y[j]*alpha + y1_const)>>16;
613 }
614 y += stride;
615 }
616
617 stride >>= 1;
618
619 for (j = 0; j < 8; j++)
620 {
621 u[j] = (u[j]*alpha + u1_const)>>16;
622 v[j] = (v[j]*alpha + v1_const)>>16;
623 }
624 u += stride;
625 v += stride;
626
627 for (i = 0; i < 6; i++)
628 {
629 u[0] = (u[0]*alpha + u1_const)>>16;
630 v[0] = (v[0]*alpha + v1_const)>>16;
631
632 u[7] = (u[7]*alpha + u1_const)>>16;
633 v[7] = (v[7]*alpha + v1_const)>>16;
634
635 u += stride;
636 v += stride;
637 }
638
639 for (j = 0; j < 8; j++)
640 {
641 u[j] = (u[j]*alpha + u1_const)>>16;
642 v[j] = (v[j]*alpha + v1_const)>>16;
643 }
644 }
645
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)646 void vp8_blend_b_c (unsigned char *y, unsigned char *u, unsigned char *v,
647 int y_1, int u_1, int v_1, int alpha, int stride)
648 {
649 int i, j;
650 int y1_const = y_1*((1<<16)-alpha);
651 int u1_const = u_1*((1<<16)-alpha);
652 int v1_const = v_1*((1<<16)-alpha);
653
654 for (i = 0; i < 4; i++)
655 {
656 for (j = 0; j < 4; j++)
657 {
658 y[j] = (y[j]*alpha + y1_const)>>16;
659 }
660 y += stride;
661 }
662
663 stride >>= 1;
664
665 for (i = 0; i < 2; i++)
666 {
667 for (j = 0; j < 2; j++)
668 {
669 u[j] = (u[j]*alpha + u1_const)>>16;
670 v[j] = (v[j]*alpha + v1_const)>>16;
671 }
672 u += stride;
673 v += stride;
674 }
675 }
676
constrain_line(int x_0,int * x_1,int y_0,int * y_1,int width,int height)677 static void constrain_line (int x_0, int *x_1, int y_0, int *y_1, int width, int height)
678 {
679 int dx;
680 int dy;
681
682 if (*x_1 > width)
683 {
684 dx = *x_1 - x_0;
685 dy = *y_1 - y_0;
686
687 *x_1 = width;
688 if (dx)
689 *y_1 = ((width-x_0)*dy)/dx + y_0;
690 }
691 if (*x_1 < 0)
692 {
693 dx = *x_1 - x_0;
694 dy = *y_1 - y_0;
695
696 *x_1 = 0;
697 if (dx)
698 *y_1 = ((0-x_0)*dy)/dx + y_0;
699 }
700 if (*y_1 > height)
701 {
702 dx = *x_1 - x_0;
703 dy = *y_1 - y_0;
704
705 *y_1 = height;
706 if (dy)
707 *x_1 = ((height-y_0)*dx)/dy + x_0;
708 }
709 if (*y_1 < 0)
710 {
711 dx = *x_1 - x_0;
712 dy = *y_1 - y_0;
713
714 *y_1 = 0;
715 if (dy)
716 *x_1 = ((0-y_0)*dx)/dy + x_0;
717 }
718 }
719
720 #if CONFIG_POSTPROC
vp8_post_proc_frame(VP8_COMMON * oci,YV12_BUFFER_CONFIG * dest,vp8_ppflags_t * ppflags)721 int vp8_post_proc_frame(VP8_COMMON *oci, YV12_BUFFER_CONFIG *dest, vp8_ppflags_t *ppflags)
722 {
723 int q = oci->filter_level * 10 / 6;
724 int flags = ppflags->post_proc_flag;
725 int deblock_level = ppflags->deblocking_level;
726 int noise_level = ppflags->noise_level;
727
728 if (!oci->frame_to_show)
729 return -1;
730
731 if (q > 63)
732 q = 63;
733
734 if (!flags)
735 {
736 *dest = *oci->frame_to_show;
737
738 /* handle problem with extending borders */
739 dest->y_width = oci->Width;
740 dest->y_height = oci->Height;
741 dest->uv_height = dest->y_height / 2;
742 oci->postproc_state.last_base_qindex = oci->base_qindex;
743 oci->postproc_state.last_frame_valid = 1;
744 return 0;
745 }
746
747 /* Allocate post_proc_buffer_int if needed */
748 if ((flags & VP8D_MFQE) && !oci->post_proc_buffer_int_used)
749 {
750 if ((flags & VP8D_DEBLOCK) || (flags & VP8D_DEMACROBLOCK))
751 {
752 int width = (oci->Width + 15) & ~15;
753 int height = (oci->Height + 15) & ~15;
754
755 if (vp8_yv12_alloc_frame_buffer(&oci->post_proc_buffer_int,
756 width, height, VP8BORDERINPIXELS))
757 vpx_internal_error(&oci->error, VPX_CODEC_MEM_ERROR,
758 "Failed to allocate MFQE framebuffer");
759
760 oci->post_proc_buffer_int_used = 1;
761
762 /* insure that postproc is set to all 0's so that post proc
763 * doesn't pull random data in from edge
764 */
765 vpx_memset((&oci->post_proc_buffer_int)->buffer_alloc,128,(&oci->post_proc_buffer)->frame_size);
766
767 }
768 }
769
770 vp8_clear_system_state();
771
772 if ((flags & VP8D_MFQE) &&
773 oci->postproc_state.last_frame_valid &&
774 oci->current_video_frame >= 2 &&
775 oci->postproc_state.last_base_qindex < 60 &&
776 oci->base_qindex - oci->postproc_state.last_base_qindex >= 20)
777 {
778 vp8_multiframe_quality_enhance(oci);
779 if (((flags & VP8D_DEBLOCK) || (flags & VP8D_DEMACROBLOCK)) &&
780 oci->post_proc_buffer_int_used)
781 {
782 vp8_yv12_copy_frame(&oci->post_proc_buffer, &oci->post_proc_buffer_int);
783 if (flags & VP8D_DEMACROBLOCK)
784 {
785 vp8_deblock(oci, &oci->post_proc_buffer_int, &oci->post_proc_buffer,
786 q + (deblock_level - 5) * 10, 1, 0);
787 vp8_de_mblock(&oci->post_proc_buffer,
788 q + (deblock_level - 5) * 10);
789 }
790 else if (flags & VP8D_DEBLOCK)
791 {
792 vp8_deblock(oci, &oci->post_proc_buffer_int, &oci->post_proc_buffer,
793 q, 1, 0);
794 }
795 }
796 /* Move partially towards the base q of the previous frame */
797 oci->postproc_state.last_base_qindex = (3*oci->postproc_state.last_base_qindex + oci->base_qindex)>>2;
798 }
799 else if (flags & VP8D_DEMACROBLOCK)
800 {
801 vp8_deblock(oci, oci->frame_to_show, &oci->post_proc_buffer,
802 q + (deblock_level - 5) * 10, 1, 0);
803 vp8_de_mblock(&oci->post_proc_buffer, q + (deblock_level - 5) * 10);
804
805 oci->postproc_state.last_base_qindex = oci->base_qindex;
806 }
807 else if (flags & VP8D_DEBLOCK)
808 {
809 vp8_deblock(oci, oci->frame_to_show, &oci->post_proc_buffer,
810 q, 1, 0);
811 oci->postproc_state.last_base_qindex = oci->base_qindex;
812 }
813 else
814 {
815 vp8_yv12_copy_frame(oci->frame_to_show, &oci->post_proc_buffer);
816 oci->postproc_state.last_base_qindex = oci->base_qindex;
817 }
818 oci->postproc_state.last_frame_valid = 1;
819
820 if (flags & VP8D_ADDNOISE)
821 {
822 if (oci->postproc_state.last_q != q
823 || oci->postproc_state.last_noise != noise_level)
824 {
825 fillrd(&oci->postproc_state, 63 - q, noise_level);
826 }
827
828 vp8_plane_add_noise
829 (oci->post_proc_buffer.y_buffer,
830 oci->postproc_state.noise,
831 oci->postproc_state.blackclamp,
832 oci->postproc_state.whiteclamp,
833 oci->postproc_state.bothclamp,
834 oci->post_proc_buffer.y_width, oci->post_proc_buffer.y_height,
835 oci->post_proc_buffer.y_stride);
836 }
837
838 #if CONFIG_POSTPROC_VISUALIZER
839 if (flags & VP8D_DEBUG_TXT_FRAME_INFO)
840 {
841 char message[512];
842 sprintf(message, "F%1dG%1dQ%3dF%3dP%d_s%dx%d",
843 (oci->frame_type == KEY_FRAME),
844 oci->refresh_golden_frame,
845 oci->base_qindex,
846 oci->filter_level,
847 flags,
848 oci->mb_cols, oci->mb_rows);
849 vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
850 }
851
852 if (flags & VP8D_DEBUG_TXT_MBLK_MODES)
853 {
854 int i, j;
855 unsigned char *y_ptr;
856 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
857 int mb_rows = post->y_height >> 4;
858 int mb_cols = post->y_width >> 4;
859 int mb_index = 0;
860 MODE_INFO *mi = oci->mi;
861
862 y_ptr = post->y_buffer + 4 * post->y_stride + 4;
863
864 /* vp8_filter each macro block */
865 for (i = 0; i < mb_rows; i++)
866 {
867 for (j = 0; j < mb_cols; j++)
868 {
869 char zz[4];
870
871 sprintf(zz, "%c", mi[mb_index].mbmi.mode + 'a');
872
873 vp8_blit_text(zz, y_ptr, post->y_stride);
874 mb_index ++;
875 y_ptr += 16;
876 }
877
878 mb_index ++; /* border */
879 y_ptr += post->y_stride * 16 - post->y_width;
880
881 }
882 }
883
884 if (flags & VP8D_DEBUG_TXT_DC_DIFF)
885 {
886 int i, j;
887 unsigned char *y_ptr;
888 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
889 int mb_rows = post->y_height >> 4;
890 int mb_cols = post->y_width >> 4;
891 int mb_index = 0;
892 MODE_INFO *mi = oci->mi;
893
894 y_ptr = post->y_buffer + 4 * post->y_stride + 4;
895
896 /* vp8_filter each macro block */
897 for (i = 0; i < mb_rows; i++)
898 {
899 for (j = 0; j < mb_cols; j++)
900 {
901 char zz[4];
902 int dc_diff = !(mi[mb_index].mbmi.mode != B_PRED &&
903 mi[mb_index].mbmi.mode != SPLITMV &&
904 mi[mb_index].mbmi.mb_skip_coeff);
905
906 if (oci->frame_type == KEY_FRAME)
907 sprintf(zz, "a");
908 else
909 sprintf(zz, "%c", dc_diff + '0');
910
911 vp8_blit_text(zz, y_ptr, post->y_stride);
912 mb_index ++;
913 y_ptr += 16;
914 }
915
916 mb_index ++; /* border */
917 y_ptr += post->y_stride * 16 - post->y_width;
918
919 }
920 }
921
922 if (flags & VP8D_DEBUG_TXT_RATE_INFO)
923 {
924 char message[512];
925 sprintf(message, "Bitrate: %10.2f framerate: %10.2f ", oci->bitrate, oci->framerate);
926 vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
927 }
928
929 /* Draw motion vectors */
930 if ((flags & VP8D_DEBUG_DRAW_MV) && ppflags->display_mv_flag)
931 {
932 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
933 int width = post->y_width;
934 int height = post->y_height;
935 unsigned char *y_buffer = oci->post_proc_buffer.y_buffer;
936 int y_stride = oci->post_proc_buffer.y_stride;
937 MODE_INFO *mi = oci->mi;
938 int x0, y0;
939
940 for (y0 = 0; y0 < height; y0 += 16)
941 {
942 for (x0 = 0; x0 < width; x0 += 16)
943 {
944 int x1, y1;
945
946 if (!(ppflags->display_mv_flag & (1<<mi->mbmi.mode)))
947 {
948 mi++;
949 continue;
950 }
951
952 if (mi->mbmi.mode == SPLITMV)
953 {
954 switch (mi->mbmi.partitioning)
955 {
956 case 0 : /* mv_top_bottom */
957 {
958 union b_mode_info *bmi = &mi->bmi[0];
959 MV *mv = &bmi->mv.as_mv;
960
961 x1 = x0 + 8 + (mv->col >> 3);
962 y1 = y0 + 4 + (mv->row >> 3);
963
964 constrain_line (x0+8, &x1, y0+4, &y1, width, height);
965 vp8_blit_line (x0+8, x1, y0+4, y1, y_buffer, y_stride);
966
967 bmi = &mi->bmi[8];
968
969 x1 = x0 + 8 + (mv->col >> 3);
970 y1 = y0 +12 + (mv->row >> 3);
971
972 constrain_line (x0+8, &x1, y0+12, &y1, width, height);
973 vp8_blit_line (x0+8, x1, y0+12, y1, y_buffer, y_stride);
974
975 break;
976 }
977 case 1 : /* mv_left_right */
978 {
979 union b_mode_info *bmi = &mi->bmi[0];
980 MV *mv = &bmi->mv.as_mv;
981
982 x1 = x0 + 4 + (mv->col >> 3);
983 y1 = y0 + 8 + (mv->row >> 3);
984
985 constrain_line (x0+4, &x1, y0+8, &y1, width, height);
986 vp8_blit_line (x0+4, x1, y0+8, y1, y_buffer, y_stride);
987
988 bmi = &mi->bmi[2];
989
990 x1 = x0 +12 + (mv->col >> 3);
991 y1 = y0 + 8 + (mv->row >> 3);
992
993 constrain_line (x0+12, &x1, y0+8, &y1, width, height);
994 vp8_blit_line (x0+12, x1, y0+8, y1, y_buffer, y_stride);
995
996 break;
997 }
998 case 2 : /* mv_quarters */
999 {
1000 union b_mode_info *bmi = &mi->bmi[0];
1001 MV *mv = &bmi->mv.as_mv;
1002
1003 x1 = x0 + 4 + (mv->col >> 3);
1004 y1 = y0 + 4 + (mv->row >> 3);
1005
1006 constrain_line (x0+4, &x1, y0+4, &y1, width, height);
1007 vp8_blit_line (x0+4, x1, y0+4, y1, y_buffer, y_stride);
1008
1009 bmi = &mi->bmi[2];
1010
1011 x1 = x0 +12 + (mv->col >> 3);
1012 y1 = y0 + 4 + (mv->row >> 3);
1013
1014 constrain_line (x0+12, &x1, y0+4, &y1, width, height);
1015 vp8_blit_line (x0+12, x1, y0+4, y1, y_buffer, y_stride);
1016
1017 bmi = &mi->bmi[8];
1018
1019 x1 = x0 + 4 + (mv->col >> 3);
1020 y1 = y0 +12 + (mv->row >> 3);
1021
1022 constrain_line (x0+4, &x1, y0+12, &y1, width, height);
1023 vp8_blit_line (x0+4, x1, y0+12, y1, y_buffer, y_stride);
1024
1025 bmi = &mi->bmi[10];
1026
1027 x1 = x0 +12 + (mv->col >> 3);
1028 y1 = y0 +12 + (mv->row >> 3);
1029
1030 constrain_line (x0+12, &x1, y0+12, &y1, width, height);
1031 vp8_blit_line (x0+12, x1, y0+12, y1, y_buffer, y_stride);
1032 break;
1033 }
1034 default :
1035 {
1036 union b_mode_info *bmi = mi->bmi;
1037 int bx0, by0;
1038
1039 for (by0 = y0; by0 < (y0+16); by0 += 4)
1040 {
1041 for (bx0 = x0; bx0 < (x0+16); bx0 += 4)
1042 {
1043 MV *mv = &bmi->mv.as_mv;
1044
1045 x1 = bx0 + 2 + (mv->col >> 3);
1046 y1 = by0 + 2 + (mv->row >> 3);
1047
1048 constrain_line (bx0+2, &x1, by0+2, &y1, width, height);
1049 vp8_blit_line (bx0+2, x1, by0+2, y1, y_buffer, y_stride);
1050
1051 bmi++;
1052 }
1053 }
1054 }
1055 }
1056 }
1057 else if (mi->mbmi.mode >= NEARESTMV)
1058 {
1059 MV *mv = &mi->mbmi.mv.as_mv;
1060 const int lx0 = x0 + 8;
1061 const int ly0 = y0 + 8;
1062
1063 x1 = lx0 + (mv->col >> 3);
1064 y1 = ly0 + (mv->row >> 3);
1065
1066 if (x1 != lx0 && y1 != ly0)
1067 {
1068 constrain_line (lx0, &x1, ly0-1, &y1, width, height);
1069 vp8_blit_line (lx0, x1, ly0-1, y1, y_buffer, y_stride);
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 else
1075 vp8_blit_line (lx0, x1, ly0, y1, y_buffer, y_stride);
1076 }
1077
1078 mi++;
1079 }
1080 mi++;
1081 }
1082 }
1083
1084 /* Color in block modes */
1085 if ((flags & VP8D_DEBUG_CLR_BLK_MODES)
1086 && (ppflags->display_mb_modes_flag || ppflags->display_b_modes_flag))
1087 {
1088 int y, x;
1089 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
1090 int width = post->y_width;
1091 int height = post->y_height;
1092 unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
1093 unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
1094 unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
1095 int y_stride = oci->post_proc_buffer.y_stride;
1096 MODE_INFO *mi = oci->mi;
1097
1098 for (y = 0; y < height; y += 16)
1099 {
1100 for (x = 0; x < width; x += 16)
1101 {
1102 int Y = 0, U = 0, V = 0;
1103
1104 if (mi->mbmi.mode == B_PRED &&
1105 ((ppflags->display_mb_modes_flag & B_PRED) || ppflags->display_b_modes_flag))
1106 {
1107 int by, bx;
1108 unsigned char *yl, *ul, *vl;
1109 union b_mode_info *bmi = mi->bmi;
1110
1111 yl = y_ptr + x;
1112 ul = u_ptr + (x>>1);
1113 vl = v_ptr + (x>>1);
1114
1115 for (by = 0; by < 16; by += 4)
1116 {
1117 for (bx = 0; bx < 16; bx += 4)
1118 {
1119 if ((ppflags->display_b_modes_flag & (1<<mi->mbmi.mode))
1120 || (ppflags->display_mb_modes_flag & B_PRED))
1121 {
1122 Y = B_PREDICTION_MODE_colors[bmi->as_mode][0];
1123 U = B_PREDICTION_MODE_colors[bmi->as_mode][1];
1124 V = B_PREDICTION_MODE_colors[bmi->as_mode][2];
1125
1126 vp8_blend_b
1127 (yl+bx, ul+(bx>>1), vl+(bx>>1), Y, U, V, 0xc000, y_stride);
1128 }
1129 bmi++;
1130 }
1131
1132 yl += y_stride*4;
1133 ul += y_stride*1;
1134 vl += y_stride*1;
1135 }
1136 }
1137 else if (ppflags->display_mb_modes_flag & (1<<mi->mbmi.mode))
1138 {
1139 Y = MB_PREDICTION_MODE_colors[mi->mbmi.mode][0];
1140 U = MB_PREDICTION_MODE_colors[mi->mbmi.mode][1];
1141 V = MB_PREDICTION_MODE_colors[mi->mbmi.mode][2];
1142
1143 vp8_blend_mb_inner
1144 (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1145 }
1146
1147 mi++;
1148 }
1149 y_ptr += y_stride*16;
1150 u_ptr += y_stride*4;
1151 v_ptr += y_stride*4;
1152
1153 mi++;
1154 }
1155 }
1156
1157 /* Color in frame reference blocks */
1158 if ((flags & VP8D_DEBUG_CLR_FRM_REF_BLKS) && ppflags->display_ref_frame_flag)
1159 {
1160 int y, x;
1161 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
1162 int width = post->y_width;
1163 int height = post->y_height;
1164 unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
1165 unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
1166 unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
1167 int y_stride = oci->post_proc_buffer.y_stride;
1168 MODE_INFO *mi = oci->mi;
1169
1170 for (y = 0; y < height; y += 16)
1171 {
1172 for (x = 0; x < width; x +=16)
1173 {
1174 int Y = 0, U = 0, V = 0;
1175
1176 if (ppflags->display_ref_frame_flag & (1<<mi->mbmi.ref_frame))
1177 {
1178 Y = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][0];
1179 U = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][1];
1180 V = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][2];
1181
1182 vp8_blend_mb_outer
1183 (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1184 }
1185
1186 mi++;
1187 }
1188 y_ptr += y_stride*16;
1189 u_ptr += y_stride*4;
1190 v_ptr += y_stride*4;
1191
1192 mi++;
1193 }
1194 }
1195 #endif
1196
1197 *dest = oci->post_proc_buffer;
1198
1199 /* handle problem with extending borders */
1200 dest->y_width = oci->Width;
1201 dest->y_height = oci->Height;
1202 dest->uv_height = dest->y_height / 2;
1203 return 0;
1204 }
1205 #endif
1206