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 }
vp8_mbpost_proc_across_ip_c(unsigned char * src,int pitch,int rows,int cols,int flimit)217 void vp8_mbpost_proc_across_ip_c(unsigned char *src, int pitch, int rows, int cols, int flimit)
218 {
219 int r, c, i;
220
221 unsigned char *s = src;
222 unsigned char d[16];
223
224 for (r = 0; r < rows; r++)
225 {
226 int sumsq = 0;
227 int sum = 0;
228
229 for (i = -8; i<0; i++)
230 s[i]=s[0];
231
232 /* 17 avoids valgrind warning - we buffer values in c in d
233 * and only write them when we've read 8 ahead...
234 */
235 for (i = cols; i<cols+17; i++)
236 s[i]=s[cols-1];
237
238 for (i = -8; i <= 6; i++)
239 {
240 sumsq += s[i] * s[i];
241 sum += s[i];
242 d[i+8] = 0;
243 }
244
245 for (c = 0; c < cols + 8; c++)
246 {
247 int x = s[c+7] - s[c-8];
248 int y = s[c+7] + s[c-8];
249
250 sum += x;
251 sumsq += x * y;
252
253 d[c&15] = s[c];
254
255 if (sumsq * 15 - sum * sum < flimit)
256 {
257 d[c&15] = (8 + sum + s[c]) >> 4;
258 }
259
260 s[c-8] = d[(c-8)&15];
261 }
262
263 s += pitch;
264 }
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 = rows; i < rows+17; i++)
288 s[i*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
vp8_de_mblock(YV12_BUFFER_CONFIG * post,int q)313 static void vp8_de_mblock(YV12_BUFFER_CONFIG *post,
314 int q)
315 {
316 vp8_mbpost_proc_across_ip(post->y_buffer, post->y_stride, post->y_height,
317 post->y_width, q2mbl(q));
318 vp8_mbpost_proc_down(post->y_buffer, post->y_stride, post->y_height,
319 post->y_width, q2mbl(q));
320 }
321
vp8_deblock(VP8_COMMON * cm,YV12_BUFFER_CONFIG * source,YV12_BUFFER_CONFIG * post,int q,int low_var_thresh,int flag)322 void vp8_deblock(VP8_COMMON *cm,
323 YV12_BUFFER_CONFIG *source,
324 YV12_BUFFER_CONFIG *post,
325 int q,
326 int low_var_thresh,
327 int flag)
328 {
329 double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
330 int ppl = (int)(level + .5);
331
332 const MODE_INFO *mode_info_context = cm->show_frame_mi;
333 int mbr, mbc;
334
335 /* The pixel thresholds are adjusted according to if or not the macroblock
336 * is a skipped block. */
337 unsigned char *ylimits = cm->pp_limits_buffer;
338 unsigned char *uvlimits = cm->pp_limits_buffer + 16 * cm->mb_cols;
339 (void) low_var_thresh;
340 (void) flag;
341
342 if (ppl > 0)
343 {
344 for (mbr = 0; mbr < cm->mb_rows; mbr++)
345 {
346 unsigned char *ylptr = ylimits;
347 unsigned char *uvlptr = uvlimits;
348 for (mbc = 0; mbc < cm->mb_cols; mbc++)
349 {
350 unsigned char mb_ppl;
351
352 if (mode_info_context->mbmi.mb_skip_coeff)
353 mb_ppl = (unsigned char)ppl >> 1;
354 else
355 mb_ppl = (unsigned char)ppl;
356
357 vpx_memset(ylptr, mb_ppl, 16);
358 vpx_memset(uvlptr, mb_ppl, 8);
359
360 ylptr += 16;
361 uvlptr += 8;
362 mode_info_context++;
363 }
364 mode_info_context++;
365
366 vp8_post_proc_down_and_across_mb_row(
367 source->y_buffer + 16 * mbr * source->y_stride,
368 post->y_buffer + 16 * mbr * post->y_stride, source->y_stride,
369 post->y_stride, source->y_width, ylimits, 16);
370
371 vp8_post_proc_down_and_across_mb_row(
372 source->u_buffer + 8 * mbr * source->uv_stride,
373 post->u_buffer + 8 * mbr * post->uv_stride, source->uv_stride,
374 post->uv_stride, source->uv_width, uvlimits, 8);
375 vp8_post_proc_down_and_across_mb_row(
376 source->v_buffer + 8 * mbr * source->uv_stride,
377 post->v_buffer + 8 * mbr * post->uv_stride, source->uv_stride,
378 post->uv_stride, source->uv_width, uvlimits, 8);
379 }
380 } else
381 {
382 vp8_yv12_copy_frame(source, post);
383 }
384 }
385
386 #if !(CONFIG_TEMPORAL_DENOISING)
vp8_de_noise(VP8_COMMON * cm,YV12_BUFFER_CONFIG * source,YV12_BUFFER_CONFIG * post,int q,int low_var_thresh,int flag)387 void vp8_de_noise(VP8_COMMON *cm,
388 YV12_BUFFER_CONFIG *source,
389 YV12_BUFFER_CONFIG *post,
390 int q,
391 int low_var_thresh,
392 int flag)
393 {
394 double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
395 int ppl = (int)(level + .5);
396 int mb_rows = source->y_width >> 4;
397 int mb_cols = source->y_height >> 4;
398 unsigned char *limits = cm->pp_limits_buffer;;
399 int mbr, mbc;
400 (void) post;
401 (void) low_var_thresh;
402 (void) flag;
403
404 vpx_memset(limits, (unsigned char)ppl, 16 * mb_cols);
405
406 /* TODO: The original code don't filter the 2 outer rows and columns. */
407 for (mbr = 0; mbr < mb_rows; mbr++)
408 {
409 vp8_post_proc_down_and_across_mb_row(
410 source->y_buffer + 16 * mbr * source->y_stride,
411 source->y_buffer + 16 * mbr * source->y_stride,
412 source->y_stride, source->y_stride, source->y_width, limits, 16);
413
414 vp8_post_proc_down_and_across_mb_row(
415 source->u_buffer + 8 * mbr * source->uv_stride,
416 source->u_buffer + 8 * mbr * source->uv_stride,
417 source->uv_stride, source->uv_stride, source->uv_width, limits, 8);
418 vp8_post_proc_down_and_across_mb_row(
419 source->v_buffer + 8 * mbr * source->uv_stride,
420 source->v_buffer + 8 * mbr * source->uv_stride,
421 source->uv_stride, source->uv_stride, source->uv_width, limits, 8);
422 }
423 }
424 #endif
425
vp8_gaussian(double sigma,double mu,double x)426 double vp8_gaussian(double sigma, double mu, double x)
427 {
428 return 1 / (sigma * sqrt(2.0 * 3.14159265)) *
429 (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma)));
430 }
431
fillrd(struct postproc_state * state,int q,int a)432 static void fillrd(struct postproc_state *state, int q, int a)
433 {
434 char char_dist[300];
435
436 double sigma;
437 int i;
438
439 vp8_clear_system_state();
440
441
442 sigma = a + .5 + .6 * (63 - q) / 63.0;
443
444 /* set up a lookup table of 256 entries that matches
445 * a gaussian distribution with sigma determined by q.
446 */
447 {
448 int next, j;
449
450 next = 0;
451
452 for (i = -32; i < 32; i++)
453 {
454 const int v = (int)(.5 + 256 * vp8_gaussian(sigma, 0, i));
455
456 if (v)
457 {
458 for (j = 0; j < v; j++)
459 {
460 char_dist[next+j] = (char) i;
461 }
462
463 next = next + j;
464 }
465
466 }
467
468 for (; next < 256; next++)
469 char_dist[next] = 0;
470
471 }
472
473 for (i = 0; i < 3072; i++)
474 {
475 state->noise[i] = char_dist[rand() & 0xff];
476 }
477
478 for (i = 0; i < 16; i++)
479 {
480 state->blackclamp[i] = -char_dist[0];
481 state->whiteclamp[i] = -char_dist[0];
482 state->bothclamp[i] = -2 * char_dist[0];
483 }
484
485 state->last_q = q;
486 state->last_noise = a;
487 }
488
489 /****************************************************************************
490 *
491 * ROUTINE : plane_add_noise_c
492 *
493 * INPUTS : unsigned char *Start starting address of buffer to add gaussian
494 * noise to
495 * unsigned int Width width of plane
496 * unsigned int Height height of plane
497 * int Pitch distance between subsequent lines of frame
498 * int q quantizer used to determine amount of noise
499 * to add
500 *
501 * OUTPUTS : None.
502 *
503 * RETURNS : void.
504 *
505 * FUNCTION : adds gaussian noise to a plane of pixels
506 *
507 * SPECIAL NOTES : None.
508 *
509 ****************************************************************************/
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)510 void vp8_plane_add_noise_c(unsigned char *Start, char *noise,
511 char blackclamp[16],
512 char whiteclamp[16],
513 char bothclamp[16],
514 unsigned int Width, unsigned int Height, int Pitch)
515 {
516 unsigned int i, j;
517 (void)bothclamp;
518 for (i = 0; i < Height; i++)
519 {
520 unsigned char *Pos = Start + i * Pitch;
521 char *Ref = (char *)(noise + (rand() & 0xff));
522
523 for (j = 0; j < Width; j++)
524 {
525 if (Pos[j] < blackclamp[0])
526 Pos[j] = blackclamp[0];
527
528 if (Pos[j] > 255 + whiteclamp[0])
529 Pos[j] = 255 + whiteclamp[0];
530
531 Pos[j] += Ref[j];
532 }
533 }
534 }
535
536 /* Blend the macro block with a solid colored square. Leave the
537 * edges unblended to give distinction to macro blocks in areas
538 * filled with the same color block.
539 */
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)540 void vp8_blend_mb_inner_c (unsigned char *y, unsigned char *u, unsigned char *v,
541 int y_1, int u_1, int v_1, int alpha, int stride)
542 {
543 int i, j;
544 int y1_const = y_1*((1<<16)-alpha);
545 int u1_const = u_1*((1<<16)-alpha);
546 int v1_const = v_1*((1<<16)-alpha);
547
548 y += 2*stride + 2;
549 for (i = 0; i < 12; i++)
550 {
551 for (j = 0; j < 12; j++)
552 {
553 y[j] = (y[j]*alpha + y1_const)>>16;
554 }
555 y += stride;
556 }
557
558 stride >>= 1;
559
560 u += stride + 1;
561 v += stride + 1;
562
563 for (i = 0; i < 6; i++)
564 {
565 for (j = 0; j < 6; j++)
566 {
567 u[j] = (u[j]*alpha + u1_const)>>16;
568 v[j] = (v[j]*alpha + v1_const)>>16;
569 }
570 u += stride;
571 v += stride;
572 }
573 }
574
575 /* Blend only the edge of the macro block. Leave center
576 * unblended to allow for other visualizations to be layered.
577 */
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)578 void vp8_blend_mb_outer_c (unsigned char *y, unsigned char *u, unsigned char *v,
579 int y_1, int u_1, int v_1, int alpha, int stride)
580 {
581 int i, j;
582 int y1_const = y_1*((1<<16)-alpha);
583 int u1_const = u_1*((1<<16)-alpha);
584 int v1_const = v_1*((1<<16)-alpha);
585
586 for (i = 0; i < 2; i++)
587 {
588 for (j = 0; j < 16; j++)
589 {
590 y[j] = (y[j]*alpha + y1_const)>>16;
591 }
592 y += stride;
593 }
594
595 for (i = 0; i < 12; i++)
596 {
597 y[0] = (y[0]*alpha + y1_const)>>16;
598 y[1] = (y[1]*alpha + y1_const)>>16;
599 y[14] = (y[14]*alpha + y1_const)>>16;
600 y[15] = (y[15]*alpha + y1_const)>>16;
601 y += stride;
602 }
603
604 for (i = 0; i < 2; i++)
605 {
606 for (j = 0; j < 16; j++)
607 {
608 y[j] = (y[j]*alpha + y1_const)>>16;
609 }
610 y += stride;
611 }
612
613 stride >>= 1;
614
615 for (j = 0; j < 8; j++)
616 {
617 u[j] = (u[j]*alpha + u1_const)>>16;
618 v[j] = (v[j]*alpha + v1_const)>>16;
619 }
620 u += stride;
621 v += stride;
622
623 for (i = 0; i < 6; i++)
624 {
625 u[0] = (u[0]*alpha + u1_const)>>16;
626 v[0] = (v[0]*alpha + v1_const)>>16;
627
628 u[7] = (u[7]*alpha + u1_const)>>16;
629 v[7] = (v[7]*alpha + v1_const)>>16;
630
631 u += stride;
632 v += stride;
633 }
634
635 for (j = 0; j < 8; j++)
636 {
637 u[j] = (u[j]*alpha + u1_const)>>16;
638 v[j] = (v[j]*alpha + v1_const)>>16;
639 }
640 }
641
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)642 void vp8_blend_b_c (unsigned char *y, unsigned char *u, unsigned char *v,
643 int y_1, int u_1, int v_1, int alpha, int stride)
644 {
645 int i, j;
646 int y1_const = y_1*((1<<16)-alpha);
647 int u1_const = u_1*((1<<16)-alpha);
648 int v1_const = v_1*((1<<16)-alpha);
649
650 for (i = 0; i < 4; i++)
651 {
652 for (j = 0; j < 4; j++)
653 {
654 y[j] = (y[j]*alpha + y1_const)>>16;
655 }
656 y += stride;
657 }
658
659 stride >>= 1;
660
661 for (i = 0; i < 2; i++)
662 {
663 for (j = 0; j < 2; j++)
664 {
665 u[j] = (u[j]*alpha + u1_const)>>16;
666 v[j] = (v[j]*alpha + v1_const)>>16;
667 }
668 u += stride;
669 v += stride;
670 }
671 }
672
constrain_line(int x_0,int * x_1,int y_0,int * y_1,int width,int height)673 static void constrain_line (int x_0, int *x_1, int y_0, int *y_1, int width, int height)
674 {
675 int dx;
676 int dy;
677
678 if (*x_1 > width)
679 {
680 dx = *x_1 - x_0;
681 dy = *y_1 - y_0;
682
683 *x_1 = width;
684 if (dx)
685 *y_1 = ((width-x_0)*dy)/dx + y_0;
686 }
687 if (*x_1 < 0)
688 {
689 dx = *x_1 - x_0;
690 dy = *y_1 - y_0;
691
692 *x_1 = 0;
693 if (dx)
694 *y_1 = ((0-x_0)*dy)/dx + y_0;
695 }
696 if (*y_1 > height)
697 {
698 dx = *x_1 - x_0;
699 dy = *y_1 - y_0;
700
701 *y_1 = height;
702 if (dy)
703 *x_1 = ((height-y_0)*dx)/dy + x_0;
704 }
705 if (*y_1 < 0)
706 {
707 dx = *x_1 - x_0;
708 dy = *y_1 - y_0;
709
710 *y_1 = 0;
711 if (dy)
712 *x_1 = ((0-y_0)*dx)/dy + x_0;
713 }
714 }
715
716 #if CONFIG_POSTPROC
vp8_post_proc_frame(VP8_COMMON * oci,YV12_BUFFER_CONFIG * dest,vp8_ppflags_t * ppflags)717 int vp8_post_proc_frame(VP8_COMMON *oci, YV12_BUFFER_CONFIG *dest, vp8_ppflags_t *ppflags)
718 {
719 int q = oci->filter_level * 10 / 6;
720 int flags = ppflags->post_proc_flag;
721 int deblock_level = ppflags->deblocking_level;
722 int noise_level = ppflags->noise_level;
723
724 if (!oci->frame_to_show)
725 return -1;
726
727 if (q > 63)
728 q = 63;
729
730 if (!flags)
731 {
732 *dest = *oci->frame_to_show;
733
734 /* handle problem with extending borders */
735 dest->y_width = oci->Width;
736 dest->y_height = oci->Height;
737 dest->uv_height = dest->y_height / 2;
738 oci->postproc_state.last_base_qindex = oci->base_qindex;
739 oci->postproc_state.last_frame_valid = 1;
740 return 0;
741 }
742
743 /* Allocate post_proc_buffer_int if needed */
744 if ((flags & VP8D_MFQE) && !oci->post_proc_buffer_int_used)
745 {
746 if ((flags & VP8D_DEBLOCK) || (flags & VP8D_DEMACROBLOCK))
747 {
748 int width = (oci->Width + 15) & ~15;
749 int height = (oci->Height + 15) & ~15;
750
751 if (vp8_yv12_alloc_frame_buffer(&oci->post_proc_buffer_int,
752 width, height, VP8BORDERINPIXELS))
753 vpx_internal_error(&oci->error, VPX_CODEC_MEM_ERROR,
754 "Failed to allocate MFQE framebuffer");
755
756 oci->post_proc_buffer_int_used = 1;
757
758 /* insure that postproc is set to all 0's so that post proc
759 * doesn't pull random data in from edge
760 */
761 vpx_memset((&oci->post_proc_buffer_int)->buffer_alloc,128,(&oci->post_proc_buffer)->frame_size);
762
763 }
764 }
765
766 vp8_clear_system_state();
767
768 if ((flags & VP8D_MFQE) &&
769 oci->postproc_state.last_frame_valid &&
770 oci->current_video_frame >= 2 &&
771 oci->postproc_state.last_base_qindex < 60 &&
772 oci->base_qindex - oci->postproc_state.last_base_qindex >= 20)
773 {
774 vp8_multiframe_quality_enhance(oci);
775 if (((flags & VP8D_DEBLOCK) || (flags & VP8D_DEMACROBLOCK)) &&
776 oci->post_proc_buffer_int_used)
777 {
778 vp8_yv12_copy_frame(&oci->post_proc_buffer, &oci->post_proc_buffer_int);
779 if (flags & VP8D_DEMACROBLOCK)
780 {
781 vp8_deblock(oci, &oci->post_proc_buffer_int, &oci->post_proc_buffer,
782 q + (deblock_level - 5) * 10, 1, 0);
783 vp8_de_mblock(&oci->post_proc_buffer,
784 q + (deblock_level - 5) * 10);
785 }
786 else if (flags & VP8D_DEBLOCK)
787 {
788 vp8_deblock(oci, &oci->post_proc_buffer_int, &oci->post_proc_buffer,
789 q, 1, 0);
790 }
791 }
792 /* Move partially towards the base q of the previous frame */
793 oci->postproc_state.last_base_qindex = (3*oci->postproc_state.last_base_qindex + oci->base_qindex)>>2;
794 }
795 else if (flags & VP8D_DEMACROBLOCK)
796 {
797 vp8_deblock(oci, oci->frame_to_show, &oci->post_proc_buffer,
798 q + (deblock_level - 5) * 10, 1, 0);
799 vp8_de_mblock(&oci->post_proc_buffer, q + (deblock_level - 5) * 10);
800
801 oci->postproc_state.last_base_qindex = oci->base_qindex;
802 }
803 else if (flags & VP8D_DEBLOCK)
804 {
805 vp8_deblock(oci, oci->frame_to_show, &oci->post_proc_buffer,
806 q, 1, 0);
807 oci->postproc_state.last_base_qindex = oci->base_qindex;
808 }
809 else
810 {
811 vp8_yv12_copy_frame(oci->frame_to_show, &oci->post_proc_buffer);
812 oci->postproc_state.last_base_qindex = oci->base_qindex;
813 }
814 oci->postproc_state.last_frame_valid = 1;
815
816 if (flags & VP8D_ADDNOISE)
817 {
818 if (oci->postproc_state.last_q != q
819 || oci->postproc_state.last_noise != noise_level)
820 {
821 fillrd(&oci->postproc_state, 63 - q, noise_level);
822 }
823
824 vp8_plane_add_noise
825 (oci->post_proc_buffer.y_buffer,
826 oci->postproc_state.noise,
827 oci->postproc_state.blackclamp,
828 oci->postproc_state.whiteclamp,
829 oci->postproc_state.bothclamp,
830 oci->post_proc_buffer.y_width, oci->post_proc_buffer.y_height,
831 oci->post_proc_buffer.y_stride);
832 }
833
834 #if CONFIG_POSTPROC_VISUALIZER
835 if (flags & VP8D_DEBUG_TXT_FRAME_INFO)
836 {
837 char message[512];
838 sprintf(message, "F%1dG%1dQ%3dF%3dP%d_s%dx%d",
839 (oci->frame_type == KEY_FRAME),
840 oci->refresh_golden_frame,
841 oci->base_qindex,
842 oci->filter_level,
843 flags,
844 oci->mb_cols, oci->mb_rows);
845 vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
846 }
847
848 if (flags & VP8D_DEBUG_TXT_MBLK_MODES)
849 {
850 int i, j;
851 unsigned char *y_ptr;
852 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
853 int mb_rows = post->y_height >> 4;
854 int mb_cols = post->y_width >> 4;
855 int mb_index = 0;
856 MODE_INFO *mi = oci->mi;
857
858 y_ptr = post->y_buffer + 4 * post->y_stride + 4;
859
860 /* vp8_filter each macro block */
861 for (i = 0; i < mb_rows; i++)
862 {
863 for (j = 0; j < mb_cols; j++)
864 {
865 char zz[4];
866
867 sprintf(zz, "%c", mi[mb_index].mbmi.mode + 'a');
868
869 vp8_blit_text(zz, y_ptr, post->y_stride);
870 mb_index ++;
871 y_ptr += 16;
872 }
873
874 mb_index ++; /* border */
875 y_ptr += post->y_stride * 16 - post->y_width;
876
877 }
878 }
879
880 if (flags & VP8D_DEBUG_TXT_DC_DIFF)
881 {
882 int i, j;
883 unsigned char *y_ptr;
884 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
885 int mb_rows = post->y_height >> 4;
886 int mb_cols = post->y_width >> 4;
887 int mb_index = 0;
888 MODE_INFO *mi = oci->mi;
889
890 y_ptr = post->y_buffer + 4 * post->y_stride + 4;
891
892 /* vp8_filter each macro block */
893 for (i = 0; i < mb_rows; i++)
894 {
895 for (j = 0; j < mb_cols; j++)
896 {
897 char zz[4];
898 int dc_diff = !(mi[mb_index].mbmi.mode != B_PRED &&
899 mi[mb_index].mbmi.mode != SPLITMV &&
900 mi[mb_index].mbmi.mb_skip_coeff);
901
902 if (oci->frame_type == KEY_FRAME)
903 sprintf(zz, "a");
904 else
905 sprintf(zz, "%c", dc_diff + '0');
906
907 vp8_blit_text(zz, y_ptr, post->y_stride);
908 mb_index ++;
909 y_ptr += 16;
910 }
911
912 mb_index ++; /* border */
913 y_ptr += post->y_stride * 16 - post->y_width;
914
915 }
916 }
917
918 if (flags & VP8D_DEBUG_TXT_RATE_INFO)
919 {
920 char message[512];
921 sprintf(message, "Bitrate: %10.2f framerate: %10.2f ", oci->bitrate, oci->framerate);
922 vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
923 }
924
925 /* Draw motion vectors */
926 if ((flags & VP8D_DEBUG_DRAW_MV) && ppflags->display_mv_flag)
927 {
928 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
929 int width = post->y_width;
930 int height = post->y_height;
931 unsigned char *y_buffer = oci->post_proc_buffer.y_buffer;
932 int y_stride = oci->post_proc_buffer.y_stride;
933 MODE_INFO *mi = oci->mi;
934 int x0, y0;
935
936 for (y0 = 0; y0 < height; y0 += 16)
937 {
938 for (x0 = 0; x0 < width; x0 += 16)
939 {
940 int x1, y1;
941
942 if (!(ppflags->display_mv_flag & (1<<mi->mbmi.mode)))
943 {
944 mi++;
945 continue;
946 }
947
948 if (mi->mbmi.mode == SPLITMV)
949 {
950 switch (mi->mbmi.partitioning)
951 {
952 case 0 : /* mv_top_bottom */
953 {
954 union b_mode_info *bmi = &mi->bmi[0];
955 MV *mv = &bmi->mv.as_mv;
956
957 x1 = x0 + 8 + (mv->col >> 3);
958 y1 = y0 + 4 + (mv->row >> 3);
959
960 constrain_line (x0+8, &x1, y0+4, &y1, width, height);
961 vp8_blit_line (x0+8, x1, y0+4, y1, y_buffer, y_stride);
962
963 bmi = &mi->bmi[8];
964
965 x1 = x0 + 8 + (mv->col >> 3);
966 y1 = y0 +12 + (mv->row >> 3);
967
968 constrain_line (x0+8, &x1, y0+12, &y1, width, height);
969 vp8_blit_line (x0+8, x1, y0+12, y1, y_buffer, y_stride);
970
971 break;
972 }
973 case 1 : /* mv_left_right */
974 {
975 union b_mode_info *bmi = &mi->bmi[0];
976 MV *mv = &bmi->mv.as_mv;
977
978 x1 = x0 + 4 + (mv->col >> 3);
979 y1 = y0 + 8 + (mv->row >> 3);
980
981 constrain_line (x0+4, &x1, y0+8, &y1, width, height);
982 vp8_blit_line (x0+4, x1, y0+8, y1, y_buffer, y_stride);
983
984 bmi = &mi->bmi[2];
985
986 x1 = x0 +12 + (mv->col >> 3);
987 y1 = y0 + 8 + (mv->row >> 3);
988
989 constrain_line (x0+12, &x1, y0+8, &y1, width, height);
990 vp8_blit_line (x0+12, x1, y0+8, y1, y_buffer, y_stride);
991
992 break;
993 }
994 case 2 : /* mv_quarters */
995 {
996 union b_mode_info *bmi = &mi->bmi[0];
997 MV *mv = &bmi->mv.as_mv;
998
999 x1 = x0 + 4 + (mv->col >> 3);
1000 y1 = y0 + 4 + (mv->row >> 3);
1001
1002 constrain_line (x0+4, &x1, y0+4, &y1, width, height);
1003 vp8_blit_line (x0+4, x1, y0+4, y1, y_buffer, y_stride);
1004
1005 bmi = &mi->bmi[2];
1006
1007 x1 = x0 +12 + (mv->col >> 3);
1008 y1 = y0 + 4 + (mv->row >> 3);
1009
1010 constrain_line (x0+12, &x1, y0+4, &y1, width, height);
1011 vp8_blit_line (x0+12, x1, y0+4, y1, y_buffer, y_stride);
1012
1013 bmi = &mi->bmi[8];
1014
1015 x1 = x0 + 4 + (mv->col >> 3);
1016 y1 = y0 +12 + (mv->row >> 3);
1017
1018 constrain_line (x0+4, &x1, y0+12, &y1, width, height);
1019 vp8_blit_line (x0+4, x1, y0+12, y1, y_buffer, y_stride);
1020
1021 bmi = &mi->bmi[10];
1022
1023 x1 = x0 +12 + (mv->col >> 3);
1024 y1 = y0 +12 + (mv->row >> 3);
1025
1026 constrain_line (x0+12, &x1, y0+12, &y1, width, height);
1027 vp8_blit_line (x0+12, x1, y0+12, y1, y_buffer, y_stride);
1028 break;
1029 }
1030 default :
1031 {
1032 union b_mode_info *bmi = mi->bmi;
1033 int bx0, by0;
1034
1035 for (by0 = y0; by0 < (y0+16); by0 += 4)
1036 {
1037 for (bx0 = x0; bx0 < (x0+16); bx0 += 4)
1038 {
1039 MV *mv = &bmi->mv.as_mv;
1040
1041 x1 = bx0 + 2 + (mv->col >> 3);
1042 y1 = by0 + 2 + (mv->row >> 3);
1043
1044 constrain_line (bx0+2, &x1, by0+2, &y1, width, height);
1045 vp8_blit_line (bx0+2, x1, by0+2, y1, y_buffer, y_stride);
1046
1047 bmi++;
1048 }
1049 }
1050 }
1051 }
1052 }
1053 else if (mi->mbmi.mode >= NEARESTMV)
1054 {
1055 MV *mv = &mi->mbmi.mv.as_mv;
1056 const int lx0 = x0 + 8;
1057 const int ly0 = y0 + 8;
1058
1059 x1 = lx0 + (mv->col >> 3);
1060 y1 = ly0 + (mv->row >> 3);
1061
1062 if (x1 != lx0 && y1 != ly0)
1063 {
1064 constrain_line (lx0, &x1, ly0-1, &y1, width, height);
1065 vp8_blit_line (lx0, x1, ly0-1, y1, y_buffer, y_stride);
1066
1067 constrain_line (lx0, &x1, ly0+1, &y1, width, height);
1068 vp8_blit_line (lx0, x1, ly0+1, y1, y_buffer, y_stride);
1069 }
1070 else
1071 vp8_blit_line (lx0, x1, ly0, y1, y_buffer, y_stride);
1072 }
1073
1074 mi++;
1075 }
1076 mi++;
1077 }
1078 }
1079
1080 /* Color in block modes */
1081 if ((flags & VP8D_DEBUG_CLR_BLK_MODES)
1082 && (ppflags->display_mb_modes_flag || ppflags->display_b_modes_flag))
1083 {
1084 int y, x;
1085 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
1086 int width = post->y_width;
1087 int height = post->y_height;
1088 unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
1089 unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
1090 unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
1091 int y_stride = oci->post_proc_buffer.y_stride;
1092 MODE_INFO *mi = oci->mi;
1093
1094 for (y = 0; y < height; y += 16)
1095 {
1096 for (x = 0; x < width; x += 16)
1097 {
1098 int Y = 0, U = 0, V = 0;
1099
1100 if (mi->mbmi.mode == B_PRED &&
1101 ((ppflags->display_mb_modes_flag & B_PRED) || ppflags->display_b_modes_flag))
1102 {
1103 int by, bx;
1104 unsigned char *yl, *ul, *vl;
1105 union b_mode_info *bmi = mi->bmi;
1106
1107 yl = y_ptr + x;
1108 ul = u_ptr + (x>>1);
1109 vl = v_ptr + (x>>1);
1110
1111 for (by = 0; by < 16; by += 4)
1112 {
1113 for (bx = 0; bx < 16; bx += 4)
1114 {
1115 if ((ppflags->display_b_modes_flag & (1<<mi->mbmi.mode))
1116 || (ppflags->display_mb_modes_flag & B_PRED))
1117 {
1118 Y = B_PREDICTION_MODE_colors[bmi->as_mode][0];
1119 U = B_PREDICTION_MODE_colors[bmi->as_mode][1];
1120 V = B_PREDICTION_MODE_colors[bmi->as_mode][2];
1121
1122 vp8_blend_b
1123 (yl+bx, ul+(bx>>1), vl+(bx>>1), Y, U, V, 0xc000, y_stride);
1124 }
1125 bmi++;
1126 }
1127
1128 yl += y_stride*4;
1129 ul += y_stride*1;
1130 vl += y_stride*1;
1131 }
1132 }
1133 else if (ppflags->display_mb_modes_flag & (1<<mi->mbmi.mode))
1134 {
1135 Y = MB_PREDICTION_MODE_colors[mi->mbmi.mode][0];
1136 U = MB_PREDICTION_MODE_colors[mi->mbmi.mode][1];
1137 V = MB_PREDICTION_MODE_colors[mi->mbmi.mode][2];
1138
1139 vp8_blend_mb_inner
1140 (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1141 }
1142
1143 mi++;
1144 }
1145 y_ptr += y_stride*16;
1146 u_ptr += y_stride*4;
1147 v_ptr += y_stride*4;
1148
1149 mi++;
1150 }
1151 }
1152
1153 /* Color in frame reference blocks */
1154 if ((flags & VP8D_DEBUG_CLR_FRM_REF_BLKS) && ppflags->display_ref_frame_flag)
1155 {
1156 int y, x;
1157 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
1158 int width = post->y_width;
1159 int height = post->y_height;
1160 unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
1161 unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
1162 unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
1163 int y_stride = oci->post_proc_buffer.y_stride;
1164 MODE_INFO *mi = oci->mi;
1165
1166 for (y = 0; y < height; y += 16)
1167 {
1168 for (x = 0; x < width; x +=16)
1169 {
1170 int Y = 0, U = 0, V = 0;
1171
1172 if (ppflags->display_ref_frame_flag & (1<<mi->mbmi.ref_frame))
1173 {
1174 Y = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][0];
1175 U = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][1];
1176 V = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][2];
1177
1178 vp8_blend_mb_outer
1179 (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1180 }
1181
1182 mi++;
1183 }
1184 y_ptr += y_stride*16;
1185 u_ptr += y_stride*4;
1186 v_ptr += y_stride*4;
1187
1188 mi++;
1189 }
1190 }
1191 #endif
1192
1193 *dest = oci->post_proc_buffer;
1194
1195 /* handle problem with extending borders */
1196 dest->y_width = oci->Width;
1197 dest->y_height = oci->Height;
1198 dest->uv_height = dest->y_height / 2;
1199 return 0;
1200 }
1201 #endif
1202