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