Merge "VP9: Eliminate up_available and left_available"
[aom.git] / vp8 / common / postproc.c
blob322b61383b5bae2229d0ea478044c8df7a25ab13
1 /*
2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
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 */
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"
21 #include <limits.h>
22 #include <math.h>
23 #include <stdlib.h>
24 #include <stdio.h>
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)
31 /* global constants */
32 #if CONFIG_POSTPROC_VISUALIZER
33 static const unsigned char MB_PREDICTION_MODE_colors[MB_MODE_COUNT][3] =
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 */
47 static const unsigned char B_PREDICTION_MODE_colors[B_MODE_COUNT][3] =
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 */
65 static const unsigned char MV_REFERENCE_FRAME_colors[MAX_REF_FRAMES][3] =
67 { RGB_TO_YUV(0x00ff00) }, /* Blue */
68 { RGB_TO_YUV(0x0000ff) }, /* Green */
69 { RGB_TO_YUV(0xffff00) }, /* Yellow */
70 { RGB_TO_YUV(0xff0000) }, /* Red */
72 #endif
74 const short vp8_rv[] =
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,
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 /***********************************************************************************************************
126 void vp8_post_proc_down_and_across_mb_row_c
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
137 unsigned char *p_src, *p_dst;
138 int row;
139 int col;
140 unsigned char v;
141 unsigned char d[4];
143 for (row = 0; row < size; row++)
145 /* post_proc_down for one row */
146 p_src = src_ptr;
147 p_dst = dst_ptr;
149 for (col = 0; col < cols; col++)
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];
156 v = p_src[col];
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]))
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;
168 p_dst[col] = v;
171 /* now post_proc_across */
172 p_src = dst_ptr;
173 p_dst = dst_ptr;
175 p_src[-2] = p_src[-1] = p_src[0];
176 p_src[cols] = p_src[cols + 1] = p_src[cols - 1];
178 for (col = 0; col < cols; col++)
180 v = p_src[col];
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]))
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;
194 d[col & 3] = v;
196 if (col >= 2)
197 p_dst[col - 2] = d[(col - 2) & 3];
200 /* handle the last two pixels */
201 p_dst[col - 2] = d[(col - 2) & 3];
202 p_dst[col - 1] = d[(col - 1) & 3];
204 /* next row */
205 src_ptr += src_pixels_per_line;
206 dst_ptr += dst_pixels_per_line;
210 static int q2mbl(int x)
212 if (x < 20) x = 20;
214 x = 50 + (x - 50) * 10 / 8;
215 return x * x / 3;
218 void vp8_mbpost_proc_across_ip_c(unsigned char *src, int pitch, int rows, int cols, int flimit)
220 int r, c, i;
222 unsigned char *s = src;
223 unsigned char d[16];
225 for (r = 0; r < rows; r++)
227 int sumsq = 0;
228 int sum = 0;
230 for (i = -8; i < 0; i++)
231 s[i]=s[0];
233 /* 17 avoids valgrind warning - we buffer values in c in d
234 * and only write them when we've read 8 ahead...
236 for (i = 0; i < 17; i++)
237 s[i+cols]=s[cols-1];
239 for (i = -8; i <= 6; i++)
241 sumsq += s[i] * s[i];
242 sum += s[i];
243 d[i+8] = 0;
246 for (c = 0; c < cols + 8; c++)
248 int x = s[c+7] - s[c-8];
249 int y = s[c+7] + s[c-8];
251 sum += x;
252 sumsq += x * y;
254 d[c&15] = s[c];
256 if (sumsq * 15 - sum * sum < flimit)
258 d[c&15] = (8 + sum + s[c]) >> 4;
261 s[c-8] = d[(c-8)&15];
264 s += pitch;
268 void vp8_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols, int flimit)
270 int r, c, i;
271 const short *rv3 = &vp8_rv[63&rand()];
273 for (c = 0; c < cols; c++ )
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);
281 for (i = -8; i < 0; i++)
282 s[i*pitch]=s[0];
284 /* 17 avoids valgrind warning - we buffer values in c in d
285 * and only write them when we've read 8 ahead...
287 for (i = 0; i < 17; i++)
288 s[(i+rows)*pitch]=s[(rows-1)*pitch];
290 for (i = -8; i <= 6; i++)
292 sumsq += s[i*pitch] * s[i*pitch];
293 sum += s[i*pitch];
296 for (r = 0; r < rows + 8; r++)
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];
302 if (sumsq * 15 - sum * sum < flimit)
304 d[r&15] = (rv2[r&127] + sum + s[0]) >> 4;
306 if (r >= 8)
307 s[-8*pitch] = d[(r-8)&15];
308 s += pitch;
313 #if CONFIG_POSTPROC
314 static void vp8_de_mblock(YV12_BUFFER_CONFIG *post,
315 int q)
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));
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)
330 double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
331 int ppl = (int)(level + .5);
333 const MODE_INFO *mode_info_context = cm->show_frame_mi;
334 int mbr, mbc;
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;
343 if (ppl > 0)
345 for (mbr = 0; mbr < cm->mb_rows; mbr++)
347 unsigned char *ylptr = ylimits;
348 unsigned char *uvlptr = uvlimits;
349 for (mbc = 0; mbc < cm->mb_cols; mbc++)
351 unsigned char mb_ppl;
353 if (mode_info_context->mbmi.mb_skip_coeff)
354 mb_ppl = (unsigned char)ppl >> 1;
355 else
356 mb_ppl = (unsigned char)ppl;
358 memset(ylptr, mb_ppl, 16);
359 memset(uvlptr, mb_ppl, 8);
361 ylptr += 16;
362 uvlptr += 8;
363 mode_info_context++;
365 mode_info_context++;
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);
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);
381 } else
383 vp8_yv12_copy_frame(source, post);
386 #endif
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)
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;
406 memset(limits, (unsigned char)ppl, 16 * mb_cols);
408 /* TODO: The original code don't filter the 2 outer rows and columns. */
409 for (mbr = 0; mbr < mb_rows; mbr++)
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,
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,
430 static double gaussian(double sigma, double mu, double x)
432 return 1 / (sigma * sqrt(2.0 * 3.14159265)) *
433 (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma)));
436 static void fillrd(struct postproc_state *state, int q, int a)
438 char char_dist[300];
440 double sigma;
441 int i;
443 vp8_clear_system_state();
446 sigma = a + .5 + .6 * (63 - q) / 63.0;
448 /* set up a lookup table of 256 entries that matches
449 * a gaussian distribution with sigma determined by q.
452 int next, j;
454 next = 0;
456 for (i = -32; i < 32; i++)
458 const int v = (int)(.5 + 256 * gaussian(sigma, 0, i));
460 if (v)
462 for (j = 0; j < v; j++)
464 char_dist[next+j] = (char) i;
467 next = next + j;
472 for (; next < 256; next++)
473 char_dist[next] = 0;
477 for (i = 0; i < 3072; i++)
479 state->noise[i] = char_dist[rand() & 0xff];
482 for (i = 0; i < 16; i++)
484 state->blackclamp[i] = -char_dist[0];
485 state->whiteclamp[i] = -char_dist[0];
486 state->bothclamp[i] = -2 * char_dist[0];
489 state->last_q = q;
490 state->last_noise = a;
493 /****************************************************************************
495 * ROUTINE : plane_add_noise_c
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
505 * OUTPUTS : None.
507 * RETURNS : void.
509 * FUNCTION : adds gaussian noise to a plane of pixels
511 * SPECIAL NOTES : None.
513 ****************************************************************************/
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)
520 unsigned int i, j;
521 (void)bothclamp;
523 for (i = 0; i < Height; i++)
525 unsigned char *Pos = Start + i * Pitch;
526 char *Ref = (char *)(noise + (rand() & 0xff));
528 for (j = 0; j < Width; j++)
530 if (Pos[j] < blackclamp[0])
531 Pos[j] = blackclamp[0];
533 if (Pos[j] > 255 + whiteclamp[0])
534 Pos[j] = 255 + whiteclamp[0];
536 Pos[j] += Ref[j];
541 /* Blend the macro block with a solid colored square. Leave the
542 * edges unblended to give distinction to macro blocks in areas
543 * filled with the same color block.
545 void vp8_blend_mb_inner_c (unsigned char *y, unsigned char *u, unsigned char *v,
546 int y_1, int u_1, int v_1, int alpha, int stride)
548 int i, j;
549 int y1_const = y_1*((1<<16)-alpha);
550 int u1_const = u_1*((1<<16)-alpha);
551 int v1_const = v_1*((1<<16)-alpha);
553 y += 2*stride + 2;
554 for (i = 0; i < 12; i++)
556 for (j = 0; j < 12; j++)
558 y[j] = (y[j]*alpha + y1_const)>>16;
560 y += stride;
563 stride >>= 1;
565 u += stride + 1;
566 v += stride + 1;
568 for (i = 0; i < 6; i++)
570 for (j = 0; j < 6; j++)
572 u[j] = (u[j]*alpha + u1_const)>>16;
573 v[j] = (v[j]*alpha + v1_const)>>16;
575 u += stride;
576 v += stride;
580 /* Blend only the edge of the macro block. Leave center
581 * unblended to allow for other visualizations to be layered.
583 void vp8_blend_mb_outer_c (unsigned char *y, unsigned char *u, unsigned char *v,
584 int y_1, int u_1, int v_1, int alpha, int stride)
586 int i, j;
587 int y1_const = y_1*((1<<16)-alpha);
588 int u1_const = u_1*((1<<16)-alpha);
589 int v1_const = v_1*((1<<16)-alpha);
591 for (i = 0; i < 2; i++)
593 for (j = 0; j < 16; j++)
595 y[j] = (y[j]*alpha + y1_const)>>16;
597 y += stride;
600 for (i = 0; i < 12; i++)
602 y[0] = (y[0]*alpha + y1_const)>>16;
603 y[1] = (y[1]*alpha + y1_const)>>16;
604 y[14] = (y[14]*alpha + y1_const)>>16;
605 y[15] = (y[15]*alpha + y1_const)>>16;
606 y += stride;
609 for (i = 0; i < 2; i++)
611 for (j = 0; j < 16; j++)
613 y[j] = (y[j]*alpha + y1_const)>>16;
615 y += stride;
618 stride >>= 1;
620 for (j = 0; j < 8; j++)
622 u[j] = (u[j]*alpha + u1_const)>>16;
623 v[j] = (v[j]*alpha + v1_const)>>16;
625 u += stride;
626 v += stride;
628 for (i = 0; i < 6; i++)
630 u[0] = (u[0]*alpha + u1_const)>>16;
631 v[0] = (v[0]*alpha + v1_const)>>16;
633 u[7] = (u[7]*alpha + u1_const)>>16;
634 v[7] = (v[7]*alpha + v1_const)>>16;
636 u += stride;
637 v += stride;
640 for (j = 0; j < 8; j++)
642 u[j] = (u[j]*alpha + u1_const)>>16;
643 v[j] = (v[j]*alpha + v1_const)>>16;
647 void vp8_blend_b_c (unsigned char *y, unsigned char *u, unsigned char *v,
648 int y_1, int u_1, int v_1, int alpha, int stride)
650 int i, j;
651 int y1_const = y_1*((1<<16)-alpha);
652 int u1_const = u_1*((1<<16)-alpha);
653 int v1_const = v_1*((1<<16)-alpha);
655 for (i = 0; i < 4; i++)
657 for (j = 0; j < 4; j++)
659 y[j] = (y[j]*alpha + y1_const)>>16;
661 y += stride;
664 stride >>= 1;
666 for (i = 0; i < 2; i++)
668 for (j = 0; j < 2; j++)
670 u[j] = (u[j]*alpha + u1_const)>>16;
671 v[j] = (v[j]*alpha + v1_const)>>16;
673 u += stride;
674 v += stride;
678 #if CONFIG_POSTPROC_VISUALIZER
679 static void constrain_line (int x_0, int *x_1, int y_0, int *y_1, int width, int height)
681 int dx;
682 int dy;
684 if (*x_1 > width)
686 dx = *x_1 - x_0;
687 dy = *y_1 - y_0;
689 *x_1 = width;
690 if (dx)
691 *y_1 = ((width-x_0)*dy)/dx + y_0;
693 if (*x_1 < 0)
695 dx = *x_1 - x_0;
696 dy = *y_1 - y_0;
698 *x_1 = 0;
699 if (dx)
700 *y_1 = ((0-x_0)*dy)/dx + y_0;
702 if (*y_1 > height)
704 dx = *x_1 - x_0;
705 dy = *y_1 - y_0;
707 *y_1 = height;
708 if (dy)
709 *x_1 = ((height-y_0)*dx)/dy + x_0;
711 if (*y_1 < 0)
713 dx = *x_1 - x_0;
714 dy = *y_1 - y_0;
716 *y_1 = 0;
717 if (dy)
718 *x_1 = ((0-y_0)*dx)/dy + x_0;
721 #endif // CONFIG_POSTPROC_VISUALIZER
723 #if CONFIG_POSTPROC
724 int vp8_post_proc_frame(VP8_COMMON *oci, YV12_BUFFER_CONFIG *dest, vp8_ppflags_t *ppflags)
726 int q = oci->filter_level * 10 / 6;
727 int flags = ppflags->post_proc_flag;
728 int deblock_level = ppflags->deblocking_level;
729 int noise_level = ppflags->noise_level;
731 if (!oci->frame_to_show)
732 return -1;
734 if (q > 63)
735 q = 63;
737 if (!flags)
739 *dest = *oci->frame_to_show;
741 /* handle problem with extending borders */
742 dest->y_width = oci->Width;
743 dest->y_height = oci->Height;
744 dest->uv_height = dest->y_height / 2;
745 oci->postproc_state.last_base_qindex = oci->base_qindex;
746 oci->postproc_state.last_frame_valid = 1;
747 return 0;
750 /* Allocate post_proc_buffer_int if needed */
751 if ((flags & VP8D_MFQE) && !oci->post_proc_buffer_int_used)
753 if ((flags & VP8D_DEBLOCK) || (flags & VP8D_DEMACROBLOCK))
755 int width = (oci->Width + 15) & ~15;
756 int height = (oci->Height + 15) & ~15;
758 if (vp8_yv12_alloc_frame_buffer(&oci->post_proc_buffer_int,
759 width, height, VP8BORDERINPIXELS))
760 vpx_internal_error(&oci->error, VPX_CODEC_MEM_ERROR,
761 "Failed to allocate MFQE framebuffer");
763 oci->post_proc_buffer_int_used = 1;
765 /* insure that postproc is set to all 0's so that post proc
766 * doesn't pull random data in from edge
768 memset((&oci->post_proc_buffer_int)->buffer_alloc,128,(&oci->post_proc_buffer)->frame_size);
773 vp8_clear_system_state();
775 if ((flags & VP8D_MFQE) &&
776 oci->postproc_state.last_frame_valid &&
777 oci->current_video_frame >= 2 &&
778 oci->postproc_state.last_base_qindex < 60 &&
779 oci->base_qindex - oci->postproc_state.last_base_qindex >= 20)
781 vp8_multiframe_quality_enhance(oci);
782 if (((flags & VP8D_DEBLOCK) || (flags & VP8D_DEMACROBLOCK)) &&
783 oci->post_proc_buffer_int_used)
785 vp8_yv12_copy_frame(&oci->post_proc_buffer, &oci->post_proc_buffer_int);
786 if (flags & VP8D_DEMACROBLOCK)
788 vp8_deblock(oci, &oci->post_proc_buffer_int, &oci->post_proc_buffer,
789 q + (deblock_level - 5) * 10, 1, 0);
790 vp8_de_mblock(&oci->post_proc_buffer,
791 q + (deblock_level - 5) * 10);
793 else if (flags & VP8D_DEBLOCK)
795 vp8_deblock(oci, &oci->post_proc_buffer_int, &oci->post_proc_buffer,
796 q, 1, 0);
799 /* Move partially towards the base q of the previous frame */
800 oci->postproc_state.last_base_qindex = (3*oci->postproc_state.last_base_qindex + oci->base_qindex)>>2;
802 else if (flags & VP8D_DEMACROBLOCK)
804 vp8_deblock(oci, oci->frame_to_show, &oci->post_proc_buffer,
805 q + (deblock_level - 5) * 10, 1, 0);
806 vp8_de_mblock(&oci->post_proc_buffer, q + (deblock_level - 5) * 10);
808 oci->postproc_state.last_base_qindex = oci->base_qindex;
810 else if (flags & VP8D_DEBLOCK)
812 vp8_deblock(oci, oci->frame_to_show, &oci->post_proc_buffer,
813 q, 1, 0);
814 oci->postproc_state.last_base_qindex = oci->base_qindex;
816 else
818 vp8_yv12_copy_frame(oci->frame_to_show, &oci->post_proc_buffer);
819 oci->postproc_state.last_base_qindex = oci->base_qindex;
821 oci->postproc_state.last_frame_valid = 1;
823 if (flags & VP8D_ADDNOISE)
825 if (oci->postproc_state.last_q != q
826 || oci->postproc_state.last_noise != noise_level)
828 fillrd(&oci->postproc_state, 63 - q, noise_level);
831 vp8_plane_add_noise
832 (oci->post_proc_buffer.y_buffer,
833 oci->postproc_state.noise,
834 oci->postproc_state.blackclamp,
835 oci->postproc_state.whiteclamp,
836 oci->postproc_state.bothclamp,
837 oci->post_proc_buffer.y_width, oci->post_proc_buffer.y_height,
838 oci->post_proc_buffer.y_stride);
841 #if CONFIG_POSTPROC_VISUALIZER
842 if (flags & VP8D_DEBUG_TXT_FRAME_INFO)
844 char message[512];
845 sprintf(message, "F%1dG%1dQ%3dF%3dP%d_s%dx%d",
846 (oci->frame_type == KEY_FRAME),
847 oci->refresh_golden_frame,
848 oci->base_qindex,
849 oci->filter_level,
850 flags,
851 oci->mb_cols, oci->mb_rows);
852 vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
855 if (flags & VP8D_DEBUG_TXT_MBLK_MODES)
857 int i, j;
858 unsigned char *y_ptr;
859 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
860 int mb_rows = post->y_height >> 4;
861 int mb_cols = post->y_width >> 4;
862 int mb_index = 0;
863 MODE_INFO *mi = oci->mi;
865 y_ptr = post->y_buffer + 4 * post->y_stride + 4;
867 /* vp8_filter each macro block */
868 for (i = 0; i < mb_rows; i++)
870 for (j = 0; j < mb_cols; j++)
872 char zz[4];
874 sprintf(zz, "%c", mi[mb_index].mbmi.mode + 'a');
876 vp8_blit_text(zz, y_ptr, post->y_stride);
877 mb_index ++;
878 y_ptr += 16;
881 mb_index ++; /* border */
882 y_ptr += post->y_stride * 16 - post->y_width;
887 if (flags & VP8D_DEBUG_TXT_DC_DIFF)
889 int i, j;
890 unsigned char *y_ptr;
891 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
892 int mb_rows = post->y_height >> 4;
893 int mb_cols = post->y_width >> 4;
894 int mb_index = 0;
895 MODE_INFO *mi = oci->mi;
897 y_ptr = post->y_buffer + 4 * post->y_stride + 4;
899 /* vp8_filter each macro block */
900 for (i = 0; i < mb_rows; i++)
902 for (j = 0; j < mb_cols; j++)
904 char zz[4];
905 int dc_diff = !(mi[mb_index].mbmi.mode != B_PRED &&
906 mi[mb_index].mbmi.mode != SPLITMV &&
907 mi[mb_index].mbmi.mb_skip_coeff);
909 if (oci->frame_type == KEY_FRAME)
910 sprintf(zz, "a");
911 else
912 sprintf(zz, "%c", dc_diff + '0');
914 vp8_blit_text(zz, y_ptr, post->y_stride);
915 mb_index ++;
916 y_ptr += 16;
919 mb_index ++; /* border */
920 y_ptr += post->y_stride * 16 - post->y_width;
925 if (flags & VP8D_DEBUG_TXT_RATE_INFO)
927 char message[512];
928 sprintf(message, "Bitrate: %10.2f framerate: %10.2f ", oci->bitrate, oci->framerate);
929 vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
932 /* Draw motion vectors */
933 if ((flags & VP8D_DEBUG_DRAW_MV) && ppflags->display_mv_flag)
935 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
936 int width = post->y_width;
937 int height = post->y_height;
938 unsigned char *y_buffer = oci->post_proc_buffer.y_buffer;
939 int y_stride = oci->post_proc_buffer.y_stride;
940 MODE_INFO *mi = oci->mi;
941 int x0, y0;
943 for (y0 = 0; y0 < height; y0 += 16)
945 for (x0 = 0; x0 < width; x0 += 16)
947 int x1, y1;
949 if (!(ppflags->display_mv_flag & (1<<mi->mbmi.mode)))
951 mi++;
952 continue;
955 if (mi->mbmi.mode == SPLITMV)
957 switch (mi->mbmi.partitioning)
959 case 0 : /* mv_top_bottom */
961 union b_mode_info *bmi = &mi->bmi[0];
962 MV *mv = &bmi->mv.as_mv;
964 x1 = x0 + 8 + (mv->col >> 3);
965 y1 = y0 + 4 + (mv->row >> 3);
967 constrain_line (x0+8, &x1, y0+4, &y1, width, height);
968 vp8_blit_line (x0+8, x1, y0+4, y1, y_buffer, y_stride);
970 bmi = &mi->bmi[8];
972 x1 = x0 + 8 + (mv->col >> 3);
973 y1 = y0 +12 + (mv->row >> 3);
975 constrain_line (x0+8, &x1, y0+12, &y1, width, height);
976 vp8_blit_line (x0+8, x1, y0+12, y1, y_buffer, y_stride);
978 break;
980 case 1 : /* mv_left_right */
982 union b_mode_info *bmi = &mi->bmi[0];
983 MV *mv = &bmi->mv.as_mv;
985 x1 = x0 + 4 + (mv->col >> 3);
986 y1 = y0 + 8 + (mv->row >> 3);
988 constrain_line (x0+4, &x1, y0+8, &y1, width, height);
989 vp8_blit_line (x0+4, x1, y0+8, y1, y_buffer, y_stride);
991 bmi = &mi->bmi[2];
993 x1 = x0 +12 + (mv->col >> 3);
994 y1 = y0 + 8 + (mv->row >> 3);
996 constrain_line (x0+12, &x1, y0+8, &y1, width, height);
997 vp8_blit_line (x0+12, x1, y0+8, y1, y_buffer, y_stride);
999 break;
1001 case 2 : /* mv_quarters */
1003 union b_mode_info *bmi = &mi->bmi[0];
1004 MV *mv = &bmi->mv.as_mv;
1006 x1 = x0 + 4 + (mv->col >> 3);
1007 y1 = y0 + 4 + (mv->row >> 3);
1009 constrain_line (x0+4, &x1, y0+4, &y1, width, height);
1010 vp8_blit_line (x0+4, x1, y0+4, y1, y_buffer, y_stride);
1012 bmi = &mi->bmi[2];
1014 x1 = x0 +12 + (mv->col >> 3);
1015 y1 = y0 + 4 + (mv->row >> 3);
1017 constrain_line (x0+12, &x1, y0+4, &y1, width, height);
1018 vp8_blit_line (x0+12, x1, y0+4, y1, y_buffer, y_stride);
1020 bmi = &mi->bmi[8];
1022 x1 = x0 + 4 + (mv->col >> 3);
1023 y1 = y0 +12 + (mv->row >> 3);
1025 constrain_line (x0+4, &x1, y0+12, &y1, width, height);
1026 vp8_blit_line (x0+4, x1, y0+12, y1, y_buffer, y_stride);
1028 bmi = &mi->bmi[10];
1030 x1 = x0 +12 + (mv->col >> 3);
1031 y1 = y0 +12 + (mv->row >> 3);
1033 constrain_line (x0+12, &x1, y0+12, &y1, width, height);
1034 vp8_blit_line (x0+12, x1, y0+12, y1, y_buffer, y_stride);
1035 break;
1037 default :
1039 union b_mode_info *bmi = mi->bmi;
1040 int bx0, by0;
1042 for (by0 = y0; by0 < (y0+16); by0 += 4)
1044 for (bx0 = x0; bx0 < (x0+16); bx0 += 4)
1046 MV *mv = &bmi->mv.as_mv;
1048 x1 = bx0 + 2 + (mv->col >> 3);
1049 y1 = by0 + 2 + (mv->row >> 3);
1051 constrain_line (bx0+2, &x1, by0+2, &y1, width, height);
1052 vp8_blit_line (bx0+2, x1, by0+2, y1, y_buffer, y_stride);
1054 bmi++;
1060 else if (mi->mbmi.mode >= NEARESTMV)
1062 MV *mv = &mi->mbmi.mv.as_mv;
1063 const int lx0 = x0 + 8;
1064 const int ly0 = y0 + 8;
1066 x1 = lx0 + (mv->col >> 3);
1067 y1 = ly0 + (mv->row >> 3);
1069 if (x1 != lx0 && y1 != ly0)
1071 constrain_line (lx0, &x1, ly0-1, &y1, width, height);
1072 vp8_blit_line (lx0, x1, ly0-1, y1, y_buffer, y_stride);
1074 constrain_line (lx0, &x1, ly0+1, &y1, width, height);
1075 vp8_blit_line (lx0, x1, ly0+1, y1, y_buffer, y_stride);
1077 else
1078 vp8_blit_line (lx0, x1, ly0, y1, y_buffer, y_stride);
1081 mi++;
1083 mi++;
1087 /* Color in block modes */
1088 if ((flags & VP8D_DEBUG_CLR_BLK_MODES)
1089 && (ppflags->display_mb_modes_flag || ppflags->display_b_modes_flag))
1091 int y, x;
1092 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
1093 int width = post->y_width;
1094 int height = post->y_height;
1095 unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
1096 unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
1097 unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
1098 int y_stride = oci->post_proc_buffer.y_stride;
1099 MODE_INFO *mi = oci->mi;
1101 for (y = 0; y < height; y += 16)
1103 for (x = 0; x < width; x += 16)
1105 int Y = 0, U = 0, V = 0;
1107 if (mi->mbmi.mode == B_PRED &&
1108 ((ppflags->display_mb_modes_flag & B_PRED) || ppflags->display_b_modes_flag))
1110 int by, bx;
1111 unsigned char *yl, *ul, *vl;
1112 union b_mode_info *bmi = mi->bmi;
1114 yl = y_ptr + x;
1115 ul = u_ptr + (x>>1);
1116 vl = v_ptr + (x>>1);
1118 for (by = 0; by < 16; by += 4)
1120 for (bx = 0; bx < 16; bx += 4)
1122 if ((ppflags->display_b_modes_flag & (1<<mi->mbmi.mode))
1123 || (ppflags->display_mb_modes_flag & B_PRED))
1125 Y = B_PREDICTION_MODE_colors[bmi->as_mode][0];
1126 U = B_PREDICTION_MODE_colors[bmi->as_mode][1];
1127 V = B_PREDICTION_MODE_colors[bmi->as_mode][2];
1129 vp8_blend_b
1130 (yl+bx, ul+(bx>>1), vl+(bx>>1), Y, U, V, 0xc000, y_stride);
1132 bmi++;
1135 yl += y_stride*4;
1136 ul += y_stride*1;
1137 vl += y_stride*1;
1140 else if (ppflags->display_mb_modes_flag & (1<<mi->mbmi.mode))
1142 Y = MB_PREDICTION_MODE_colors[mi->mbmi.mode][0];
1143 U = MB_PREDICTION_MODE_colors[mi->mbmi.mode][1];
1144 V = MB_PREDICTION_MODE_colors[mi->mbmi.mode][2];
1146 vp8_blend_mb_inner
1147 (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1150 mi++;
1152 y_ptr += y_stride*16;
1153 u_ptr += y_stride*4;
1154 v_ptr += y_stride*4;
1156 mi++;
1160 /* Color in frame reference blocks */
1161 if ((flags & VP8D_DEBUG_CLR_FRM_REF_BLKS) && ppflags->display_ref_frame_flag)
1163 int y, x;
1164 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
1165 int width = post->y_width;
1166 int height = post->y_height;
1167 unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
1168 unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
1169 unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
1170 int y_stride = oci->post_proc_buffer.y_stride;
1171 MODE_INFO *mi = oci->mi;
1173 for (y = 0; y < height; y += 16)
1175 for (x = 0; x < width; x +=16)
1177 int Y = 0, U = 0, V = 0;
1179 if (ppflags->display_ref_frame_flag & (1<<mi->mbmi.ref_frame))
1181 Y = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][0];
1182 U = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][1];
1183 V = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][2];
1185 vp8_blend_mb_outer
1186 (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1189 mi++;
1191 y_ptr += y_stride*16;
1192 u_ptr += y_stride*4;
1193 v_ptr += y_stride*4;
1195 mi++;
1198 #endif
1200 *dest = oci->post_proc_buffer;
1202 /* handle problem with extending borders */
1203 dest->y_width = oci->Width;
1204 dest->y_height = oci->Height;
1205 dest->uv_height = dest->y_height / 2;
1206 return 0;
1208 #endif