Merge "vp8_rd_pick_best_mbsegmentation code restructure"
[libvpx.git] / vp8 / common / postproc.c
blob15b1c2c89e97a8ca388478772b5f7a1b0471d480
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_ports/config.h"
13 #include "vpx_scale/yv12config.h"
14 #include "postproc.h"
15 #include "vpx_scale/yv12extend.h"
16 #include "vpx_scale/vpxscale.h"
17 #include "systemdependent.h"
19 #include <math.h>
20 #include <stdlib.h>
21 #include <stdio.h>
23 #define RGB_TO_YUV(t) \
24 ( (0.257*(float)(t>>16)) + (0.504*(float)(t>>8&0xff)) + (0.098*(float)(t&0xff)) + 16), \
25 (-(0.148*(float)(t>>16)) - (0.291*(float)(t>>8&0xff)) + (0.439*(float)(t&0xff)) + 128), \
26 ( (0.439*(float)(t>>16)) - (0.368*(float)(t>>8&0xff)) - (0.071*(float)(t&0xff)) + 128)
28 /* global constants */
29 #if CONFIG_POSTPROC_VISUALIZER
30 static const unsigned char MB_PREDICTION_MODE_colors[MB_MODE_COUNT][3] =
32 { RGB_TO_YUV(0x98FB98) }, /* PaleGreen */
33 { RGB_TO_YUV(0x00FF00) }, /* Green */
34 { RGB_TO_YUV(0xADFF2F) }, /* GreenYellow */
35 { RGB_TO_YUV(0x228B22) }, /* ForestGreen */
36 { RGB_TO_YUV(0x006400) }, /* DarkGreen */
37 { RGB_TO_YUV(0x98F5FF) }, /* Cadet Blue */
38 { RGB_TO_YUV(0x6CA6CD) }, /* Sky Blue */
39 { RGB_TO_YUV(0x00008B) }, /* Dark blue */
40 { RGB_TO_YUV(0x551A8B) }, /* Purple */
41 { RGB_TO_YUV(0xFF0000) } /* Red */
44 static const unsigned char B_PREDICTION_MODE_colors[B_MODE_COUNT][3] =
46 { RGB_TO_YUV(0x6633ff) }, /* Purple */
47 { RGB_TO_YUV(0xcc33ff) }, /* Magenta */
48 { RGB_TO_YUV(0xff33cc) }, /* Pink */
49 { RGB_TO_YUV(0xff3366) }, /* Coral */
50 { RGB_TO_YUV(0x3366ff) }, /* Blue */
51 { RGB_TO_YUV(0xed00f5) }, /* Dark Blue */
52 { RGB_TO_YUV(0x2e00b8) }, /* Dark Purple */
53 { RGB_TO_YUV(0xff6633) }, /* Orange */
54 { RGB_TO_YUV(0x33ccff) }, /* Light Blue */
55 { RGB_TO_YUV(0x8ab800) }, /* Green */
56 { RGB_TO_YUV(0xffcc33) }, /* Light Orange */
57 { RGB_TO_YUV(0x33ffcc) }, /* Aqua */
58 { RGB_TO_YUV(0x66ff33) }, /* Light Green */
59 { RGB_TO_YUV(0xccff33) }, /* Yellow */
62 static const unsigned char MV_REFERENCE_FRAME_colors[MAX_REF_FRAMES][3] =
64 { RGB_TO_YUV(0x00ff00) }, /* Blue */
65 { RGB_TO_YUV(0x0000ff) }, /* Green */
66 { RGB_TO_YUV(0xffff00) }, /* Yellow */
67 { RGB_TO_YUV(0xff0000) }, /* Red */
69 #endif
71 static const short kernel5[] =
73 1, 1, 4, 1, 1
76 const short vp8_rv[] =
78 8, 5, 2, 2, 8, 12, 4, 9, 8, 3,
79 0, 3, 9, 0, 0, 0, 8, 3, 14, 4,
80 10, 1, 11, 14, 1, 14, 9, 6, 12, 11,
81 8, 6, 10, 0, 0, 8, 9, 0, 3, 14,
82 8, 11, 13, 4, 2, 9, 0, 3, 9, 6,
83 1, 2, 3, 14, 13, 1, 8, 2, 9, 7,
84 3, 3, 1, 13, 13, 6, 6, 5, 2, 7,
85 11, 9, 11, 8, 7, 3, 2, 0, 13, 13,
86 14, 4, 12, 5, 12, 10, 8, 10, 13, 10,
87 4, 14, 4, 10, 0, 8, 11, 1, 13, 7,
88 7, 14, 6, 14, 13, 2, 13, 5, 4, 4,
89 0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
90 8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
91 3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
92 3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
93 13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
94 5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
95 9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
96 4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
97 3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
98 11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
99 5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
100 0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
101 10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
102 4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
103 0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
104 8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
105 3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
106 3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
107 13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
108 5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
109 9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
110 4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
111 3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
112 11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
113 5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
114 0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
115 10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
116 4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
117 3, 8, 3, 7, 8, 5, 11, 4, 12, 3,
118 11, 9, 14, 8, 14, 13, 4, 3, 1, 2,
119 14, 6, 5, 4, 4, 11, 4, 6, 2, 1,
120 5, 8, 8, 12, 13, 5, 14, 10, 12, 13,
121 0, 9, 5, 5, 11, 10, 13, 9, 10, 13,
125 extern void vp8_blit_text(const char *msg, unsigned char *address, const int pitch);
126 extern void vp8_blit_line(int x0, int x1, int y0, int y1, unsigned char *image, const int pitch);
127 /***********************************************************************************************************
129 void vp8_post_proc_down_and_across_c
131 unsigned char *src_ptr,
132 unsigned char *dst_ptr,
133 int src_pixels_per_line,
134 int dst_pixels_per_line,
135 int rows,
136 int cols,
137 int flimit
140 unsigned char *p_src, *p_dst;
141 int row;
142 int col;
143 int i;
144 int v;
145 int pitch = src_pixels_per_line;
146 unsigned char d[8];
147 (void)dst_pixels_per_line;
149 for (row = 0; row < rows; row++)
151 /* post_proc_down for one row */
152 p_src = src_ptr;
153 p_dst = dst_ptr;
155 for (col = 0; col < cols; col++)
158 int kernel = 4;
159 int v = p_src[col];
161 for (i = -2; i <= 2; i++)
163 if (abs(v - p_src[col+i*pitch]) > flimit)
164 goto down_skip_convolve;
166 kernel += kernel5[2+i] * p_src[col+i*pitch];
169 v = (kernel >> 3);
170 down_skip_convolve:
171 p_dst[col] = v;
174 /* now post_proc_across */
175 p_src = dst_ptr;
176 p_dst = dst_ptr;
178 for (i = 0; i < 8; i++)
179 d[i] = p_src[i];
181 for (col = 0; col < cols; col++)
183 int kernel = 4;
184 v = p_src[col];
186 d[col&7] = v;
188 for (i = -2; i <= 2; i++)
190 if (abs(v - p_src[col+i]) > flimit)
191 goto across_skip_convolve;
193 kernel += kernel5[2+i] * p_src[col+i];
196 d[col&7] = (kernel >> 3);
197 across_skip_convolve:
199 if (col >= 2)
200 p_dst[col-2] = d[(col-2)&7];
203 /* handle the last two pixels */
204 p_dst[col-2] = d[(col-2)&7];
205 p_dst[col-1] = d[(col-1)&7];
208 /* next row */
209 src_ptr += pitch;
210 dst_ptr += pitch;
214 int vp8_q2mbl(int x)
216 if (x < 20) x = 20;
218 x = 50 + (x - 50) * 10 / 8;
219 return x * x / 3;
221 void vp8_mbpost_proc_across_ip_c(unsigned char *src, int pitch, int rows, int cols, int flimit)
223 int r, c, i;
225 unsigned char *s = src;
226 unsigned char d[16];
229 for (r = 0; r < rows; r++)
231 int sumsq = 0;
232 int sum = 0;
234 for (i = -8; i <= 6; i++)
236 sumsq += s[i] * s[i];
237 sum += s[i];
238 d[i+8] = 0;
241 for (c = 0; c < cols + 8; c++)
243 int x = s[c+7] - s[c-8];
244 int y = s[c+7] + s[c-8];
246 sum += x;
247 sumsq += x * y;
249 d[c&15] = s[c];
251 if (sumsq * 15 - sum * sum < flimit)
253 d[c&15] = (8 + sum + s[c]) >> 4;
256 s[c-8] = d[(c-8)&15];
259 s += pitch;
267 void vp8_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols, int flimit)
269 int r, c, i;
270 const short *rv3 = &vp8_rv[63&rand()];
272 for (c = 0; c < cols; c++)
274 unsigned char *s = &dst[c];
275 int sumsq = 0;
276 int sum = 0;
277 unsigned char d[16];
278 const short *rv2 = rv3 + ((c * 17) & 127);
280 for (i = -8; i <= 6; i++)
282 sumsq += s[i*pitch] * s[i*pitch];
283 sum += s[i*pitch];
286 for (r = 0; r < rows + 8; r++)
288 sumsq += s[7*pitch] * s[ 7*pitch] - s[-8*pitch] * s[-8*pitch];
289 sum += s[7*pitch] - s[-8*pitch];
290 d[r&15] = s[0];
292 if (sumsq * 15 - sum * sum < flimit)
294 d[r&15] = (rv2[r&127] + sum + s[0]) >> 4;
297 s[-8*pitch] = d[(r-8)&15];
298 s += pitch;
304 static void vp8_deblock_and_de_macro_block(YV12_BUFFER_CONFIG *source,
305 YV12_BUFFER_CONFIG *post,
306 int q,
307 int low_var_thresh,
308 int flag,
309 vp8_postproc_rtcd_vtable_t *rtcd)
311 double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
312 int ppl = (int)(level + .5);
313 (void) low_var_thresh;
314 (void) flag;
316 POSTPROC_INVOKE(rtcd, downacross)(source->y_buffer, post->y_buffer, source->y_stride, post->y_stride, source->y_height, source->y_width, ppl);
317 POSTPROC_INVOKE(rtcd, across)(post->y_buffer, post->y_stride, post->y_height, post->y_width, vp8_q2mbl(q));
318 POSTPROC_INVOKE(rtcd, down)(post->y_buffer, post->y_stride, post->y_height, post->y_width, vp8_q2mbl(q));
320 POSTPROC_INVOKE(rtcd, downacross)(source->u_buffer, post->u_buffer, source->uv_stride, post->uv_stride, source->uv_height, source->uv_width, ppl);
321 POSTPROC_INVOKE(rtcd, downacross)(source->v_buffer, post->v_buffer, source->uv_stride, post->uv_stride, source->uv_height, source->uv_width, ppl);
325 void vp8_deblock(YV12_BUFFER_CONFIG *source,
326 YV12_BUFFER_CONFIG *post,
327 int q,
328 int low_var_thresh,
329 int flag,
330 vp8_postproc_rtcd_vtable_t *rtcd)
332 double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
333 int ppl = (int)(level + .5);
334 (void) low_var_thresh;
335 (void) flag;
337 POSTPROC_INVOKE(rtcd, downacross)(source->y_buffer, post->y_buffer, source->y_stride, post->y_stride, source->y_height, source->y_width, ppl);
338 POSTPROC_INVOKE(rtcd, downacross)(source->u_buffer, post->u_buffer, source->uv_stride, post->uv_stride, source->uv_height, source->uv_width, ppl);
339 POSTPROC_INVOKE(rtcd, downacross)(source->v_buffer, post->v_buffer, source->uv_stride, post->uv_stride, source->uv_height, source->uv_width, ppl);
342 void vp8_de_noise(YV12_BUFFER_CONFIG *source,
343 YV12_BUFFER_CONFIG *post,
344 int q,
345 int low_var_thresh,
346 int flag,
347 vp8_postproc_rtcd_vtable_t *rtcd)
349 double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
350 int ppl = (int)(level + .5);
351 (void) post;
352 (void) low_var_thresh;
353 (void) flag;
355 POSTPROC_INVOKE(rtcd, downacross)(
356 source->y_buffer + 2 * source->y_stride + 2,
357 source->y_buffer + 2 * source->y_stride + 2,
358 source->y_stride,
359 source->y_stride,
360 source->y_height - 4,
361 source->y_width - 4,
362 ppl);
363 POSTPROC_INVOKE(rtcd, downacross)(
364 source->u_buffer + 2 * source->uv_stride + 2,
365 source->u_buffer + 2 * source->uv_stride + 2,
366 source->uv_stride,
367 source->uv_stride,
368 source->uv_height - 4,
369 source->uv_width - 4, ppl);
370 POSTPROC_INVOKE(rtcd, downacross)(
371 source->v_buffer + 2 * source->uv_stride + 2,
372 source->v_buffer + 2 * source->uv_stride + 2,
373 source->uv_stride,
374 source->uv_stride,
375 source->uv_height - 4,
376 source->uv_width - 4, ppl);
380 double vp8_gaussian(double sigma, double mu, double x)
382 return 1 / (sigma * sqrt(2.0 * 3.14159265)) *
383 (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma)));
386 extern void (*vp8_clear_system_state)(void);
389 static void fillrd(struct postproc_state *state, int q, int a)
391 char char_dist[300];
393 double sigma;
394 int ai = a, qi = q, i;
396 vp8_clear_system_state();
399 sigma = ai + .5 + .6 * (63 - qi) / 63.0;
401 /* set up a lookup table of 256 entries that matches
402 * a gaussian distribution with sigma determined by q.
405 double i;
406 int next, j;
408 next = 0;
410 for (i = -32; i < 32; i++)
412 int a = (int)(.5 + 256 * vp8_gaussian(sigma, 0, i));
414 if (a)
416 for (j = 0; j < a; j++)
418 char_dist[next+j] = (char) i;
421 next = next + j;
426 for (next = next; next < 256; next++)
427 char_dist[next] = 0;
431 for (i = 0; i < 3072; i++)
433 state->noise[i] = char_dist[rand() & 0xff];
436 for (i = 0; i < 16; i++)
438 state->blackclamp[i] = -char_dist[0];
439 state->whiteclamp[i] = -char_dist[0];
440 state->bothclamp[i] = -2 * char_dist[0];
443 state->last_q = q;
444 state->last_noise = a;
447 /****************************************************************************
449 * ROUTINE : plane_add_noise_c
451 * INPUTS : unsigned char *Start starting address of buffer to add gaussian
452 * noise to
453 * unsigned int Width width of plane
454 * unsigned int Height height of plane
455 * int Pitch distance between subsequent lines of frame
456 * int q quantizer used to determine amount of noise
457 * to add
459 * OUTPUTS : None.
461 * RETURNS : void.
463 * FUNCTION : adds gaussian noise to a plane of pixels
465 * SPECIAL NOTES : None.
467 ****************************************************************************/
468 void vp8_plane_add_noise_c(unsigned char *Start, char *noise,
469 char blackclamp[16],
470 char whiteclamp[16],
471 char bothclamp[16],
472 unsigned int Width, unsigned int Height, int Pitch)
474 unsigned int i, j;
476 for (i = 0; i < Height; i++)
478 unsigned char *Pos = Start + i * Pitch;
479 char *Ref = (char *)(noise + (rand() & 0xff));
481 for (j = 0; j < Width; j++)
483 if (Pos[j] < blackclamp[0])
484 Pos[j] = blackclamp[0];
486 if (Pos[j] > 255 + whiteclamp[0])
487 Pos[j] = 255 + whiteclamp[0];
489 Pos[j] += Ref[j];
494 /* Blend the macro block with a solid colored square. Leave the
495 * edges unblended to give distinction to macro blocks in areas
496 * filled with the same color block.
498 void vp8_blend_mb_inner_c (unsigned char *y, unsigned char *u, unsigned char *v,
499 int y1, int u1, int v1, int alpha, int stride)
501 int i, j;
502 int y1_const = y1*((1<<16)-alpha);
503 int u1_const = u1*((1<<16)-alpha);
504 int v1_const = v1*((1<<16)-alpha);
506 y += 2*stride + 2;
507 for (i = 0; i < 12; i++)
509 for (j = 0; j < 12; j++)
511 y[j] = (y[j]*alpha + y1_const)>>16;
513 y += stride;
516 stride >>= 1;
518 u += stride + 1;
519 v += stride + 1;
521 for (i = 0; i < 6; i++)
523 for (j = 0; j < 6; j++)
525 u[j] = (u[j]*alpha + u1_const)>>16;
526 v[j] = (v[j]*alpha + v1_const)>>16;
528 u += stride;
529 v += stride;
533 /* Blend only the edge of the macro block. Leave center
534 * unblended to allow for other visualizations to be layered.
536 void vp8_blend_mb_outer_c (unsigned char *y, unsigned char *u, unsigned char *v,
537 int y1, int u1, int v1, int alpha, int stride)
539 int i, j;
540 int y1_const = y1*((1<<16)-alpha);
541 int u1_const = u1*((1<<16)-alpha);
542 int v1_const = v1*((1<<16)-alpha);
544 for (i = 0; i < 2; i++)
546 for (j = 0; j < 16; j++)
548 y[j] = (y[j]*alpha + y1_const)>>16;
550 y += stride;
553 for (i = 0; i < 12; i++)
555 y[0] = (y[0]*alpha + y1_const)>>16;
556 y[1] = (y[1]*alpha + y1_const)>>16;
557 y[14] = (y[14]*alpha + y1_const)>>16;
558 y[15] = (y[15]*alpha + y1_const)>>16;
559 y += stride;
562 for (i = 0; i < 2; i++)
564 for (j = 0; j < 16; j++)
566 y[j] = (y[j]*alpha + y1_const)>>16;
568 y += stride;
571 stride >>= 1;
573 for (j = 0; j < 8; j++)
575 u[j] = (u[j]*alpha + u1_const)>>16;
576 v[j] = (v[j]*alpha + v1_const)>>16;
578 u += stride;
579 v += stride;
581 for (i = 0; i < 6; i++)
583 u[0] = (u[0]*alpha + u1_const)>>16;
584 v[0] = (v[0]*alpha + v1_const)>>16;
586 u[7] = (u[7]*alpha + u1_const)>>16;
587 v[7] = (v[7]*alpha + v1_const)>>16;
589 u += stride;
590 v += stride;
593 for (j = 0; j < 8; j++)
595 u[j] = (u[j]*alpha + u1_const)>>16;
596 v[j] = (v[j]*alpha + v1_const)>>16;
600 void vp8_blend_b_c (unsigned char *y, unsigned char *u, unsigned char *v,
601 int y1, int u1, int v1, int alpha, int stride)
603 int i, j;
604 int y1_const = y1*((1<<16)-alpha);
605 int u1_const = u1*((1<<16)-alpha);
606 int v1_const = v1*((1<<16)-alpha);
608 for (i = 0; i < 4; i++)
610 for (j = 0; j < 4; j++)
612 y[j] = (y[j]*alpha + y1_const)>>16;
614 y += stride;
617 stride >>= 1;
619 for (i = 0; i < 2; i++)
621 for (j = 0; j < 2; j++)
623 u[j] = (u[j]*alpha + u1_const)>>16;
624 v[j] = (v[j]*alpha + v1_const)>>16;
626 u += stride;
627 v += stride;
631 static void constrain_line (int x0, int *x1, int y0, int *y1, int width, int height)
633 int dx;
634 int dy;
636 if (*x1 > width)
638 dx = *x1 - x0;
639 dy = *y1 - y0;
641 *x1 = width;
642 if (dx)
643 *y1 = ((width-x0)*dy)/dx + y0;
645 if (*x1 < 0)
647 dx = *x1 - x0;
648 dy = *y1 - y0;
650 *x1 = 0;
651 if (dx)
652 *y1 = ((0-x0)*dy)/dx + y0;
654 if (*y1 > height)
656 dx = *x1 - x0;
657 dy = *y1 - y0;
659 *y1 = height;
660 if (dy)
661 *x1 = ((height-y0)*dx)/dy + x0;
663 if (*y1 < 0)
665 dx = *x1 - x0;
666 dy = *y1 - y0;
668 *y1 = 0;
669 if (dy)
670 *x1 = ((0-y0)*dx)/dy + x0;
675 #if CONFIG_RUNTIME_CPU_DETECT
676 #define RTCD_VTABLE(oci) (&(oci)->rtcd.postproc)
677 #else
678 #define RTCD_VTABLE(oci) NULL
679 #endif
681 int vp8_post_proc_frame(VP8_COMMON *oci, YV12_BUFFER_CONFIG *dest, vp8_ppflags_t *ppflags)
683 char message[512];
684 int q = oci->filter_level * 10 / 6;
685 int flags = ppflags->post_proc_flag;
686 int deblock_level = ppflags->deblocking_level;
687 int noise_level = ppflags->noise_level;
689 if (!oci->frame_to_show)
690 return -1;
692 if (q > 63)
693 q = 63;
695 if (!flags)
697 *dest = *oci->frame_to_show;
699 /* handle problem with extending borders */
700 dest->y_width = oci->Width;
701 dest->y_height = oci->Height;
702 dest->uv_height = dest->y_height / 2;
703 return 0;
707 #if ARCH_X86||ARCH_X86_64
708 vpx_reset_mmx_state();
709 #endif
711 if (flags & VP8D_DEMACROBLOCK)
713 vp8_deblock_and_de_macro_block(oci->frame_to_show, &oci->post_proc_buffer,
714 q + (deblock_level - 5) * 10, 1, 0, RTCD_VTABLE(oci));
716 else if (flags & VP8D_DEBLOCK)
718 vp8_deblock(oci->frame_to_show, &oci->post_proc_buffer,
719 q, 1, 0, RTCD_VTABLE(oci));
721 else
723 vp8_yv12_copy_frame_ptr(oci->frame_to_show, &oci->post_proc_buffer);
726 if (flags & VP8D_ADDNOISE)
728 if (oci->postproc_state.last_q != q
729 || oci->postproc_state.last_noise != noise_level)
731 fillrd(&oci->postproc_state, 63 - q, noise_level);
734 POSTPROC_INVOKE(RTCD_VTABLE(oci), addnoise)
735 (oci->post_proc_buffer.y_buffer,
736 oci->postproc_state.noise,
737 oci->postproc_state.blackclamp,
738 oci->postproc_state.whiteclamp,
739 oci->postproc_state.bothclamp,
740 oci->post_proc_buffer.y_width, oci->post_proc_buffer.y_height,
741 oci->post_proc_buffer.y_stride);
744 #if CONFIG_POSTPROC_VISUALIZER
745 if (flags & VP8D_DEBUG_TXT_FRAME_INFO)
747 sprintf(message, "F%1dG%1dQ%3dF%3dP%d_s%dx%d",
748 (oci->frame_type == KEY_FRAME),
749 oci->refresh_golden_frame,
750 oci->base_qindex,
751 oci->filter_level,
752 flags,
753 oci->mb_cols, oci->mb_rows);
754 vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
757 if (flags & VP8D_DEBUG_TXT_MBLK_MODES)
759 int i, j;
760 unsigned char *y_ptr;
761 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
762 int mb_rows = post->y_height >> 4;
763 int mb_cols = post->y_width >> 4;
764 int mb_index = 0;
765 MODE_INFO *mi = oci->mi;
767 y_ptr = post->y_buffer + 4 * post->y_stride + 4;
769 /* vp8_filter each macro block */
770 for (i = 0; i < mb_rows; i++)
772 for (j = 0; j < mb_cols; j++)
774 char zz[4];
776 sprintf(zz, "%c", mi[mb_index].mbmi.mode + 'a');
778 vp8_blit_text(zz, y_ptr, post->y_stride);
779 mb_index ++;
780 y_ptr += 16;
783 mb_index ++; /* border */
784 y_ptr += post->y_stride * 16 - post->y_width;
789 if (flags & VP8D_DEBUG_TXT_DC_DIFF)
791 int i, j;
792 unsigned char *y_ptr;
793 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
794 int mb_rows = post->y_height >> 4;
795 int mb_cols = post->y_width >> 4;
796 int mb_index = 0;
797 MODE_INFO *mi = oci->mi;
799 y_ptr = post->y_buffer + 4 * post->y_stride + 4;
801 /* vp8_filter each macro block */
802 for (i = 0; i < mb_rows; i++)
804 for (j = 0; j < mb_cols; j++)
806 char zz[4];
808 if (oci->frame_type == KEY_FRAME)
809 sprintf(zz, "a");
810 else
811 sprintf(zz, "%c", mi[mb_index].mbmi.dc_diff + '0');
813 vp8_blit_text(zz, y_ptr, post->y_stride);
814 mb_index ++;
815 y_ptr += 16;
818 mb_index ++; /* border */
819 y_ptr += post->y_stride * 16 - post->y_width;
824 if (flags & VP8D_DEBUG_TXT_RATE_INFO)
826 sprintf(message, "Bitrate: %10.2f frame_rate: %10.2f ", oci->bitrate, oci->framerate);
827 vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
830 /* Draw motion vectors */
831 if ((flags & VP8D_DEBUG_DRAW_MV) && ppflags->display_mv_flag)
833 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
834 int width = post->y_width;
835 int height = post->y_height;
836 int mb_cols = width >> 4;
837 unsigned char *y_buffer = oci->post_proc_buffer.y_buffer;
838 int y_stride = oci->post_proc_buffer.y_stride;
839 MODE_INFO *mi = oci->mi;
840 int x0, y0;
842 for (y0 = 0; y0 < height; y0 += 16)
844 for (x0 = 0; x0 < width; x0 += 16)
846 int x1, y1;
848 if (!(ppflags->display_mv_flag & (1<<mi->mbmi.mode)))
850 mi++;
851 continue;
854 if (mi->mbmi.mode == SPLITMV)
856 switch (mi->mbmi.partitioning)
858 case 0 : /* mv_top_bottom */
860 B_MODE_INFO *bmi = &mi->bmi[0];
861 MV *mv = &bmi->mv.as_mv;
863 x1 = x0 + 8 + (mv->col >> 3);
864 y1 = y0 + 4 + (mv->row >> 3);
866 constrain_line (x0+8, &x1, y0+4, &y1, width, height);
867 vp8_blit_line (x0+8, x1, y0+4, y1, y_buffer, y_stride);
869 bmi = &mi->bmi[8];
871 x1 = x0 + 8 + (mv->col >> 3);
872 y1 = y0 +12 + (mv->row >> 3);
874 constrain_line (x0+8, &x1, y0+12, &y1, width, height);
875 vp8_blit_line (x0+8, x1, y0+12, y1, y_buffer, y_stride);
877 break;
879 case 1 : /* mv_left_right */
881 B_MODE_INFO *bmi = &mi->bmi[0];
882 MV *mv = &bmi->mv.as_mv;
884 x1 = x0 + 4 + (mv->col >> 3);
885 y1 = y0 + 8 + (mv->row >> 3);
887 constrain_line (x0+4, &x1, y0+8, &y1, width, height);
888 vp8_blit_line (x0+4, x1, y0+8, y1, y_buffer, y_stride);
890 bmi = &mi->bmi[2];
892 x1 = x0 +12 + (mv->col >> 3);
893 y1 = y0 + 8 + (mv->row >> 3);
895 constrain_line (x0+12, &x1, y0+8, &y1, width, height);
896 vp8_blit_line (x0+12, x1, y0+8, y1, y_buffer, y_stride);
898 break;
900 case 2 : /* mv_quarters */
902 B_MODE_INFO *bmi = &mi->bmi[0];
903 MV *mv = &bmi->mv.as_mv;
905 x1 = x0 + 4 + (mv->col >> 3);
906 y1 = y0 + 4 + (mv->row >> 3);
908 constrain_line (x0+4, &x1, y0+4, &y1, width, height);
909 vp8_blit_line (x0+4, x1, y0+4, y1, y_buffer, y_stride);
911 bmi = &mi->bmi[2];
913 x1 = x0 +12 + (mv->col >> 3);
914 y1 = y0 + 4 + (mv->row >> 3);
916 constrain_line (x0+12, &x1, y0+4, &y1, width, height);
917 vp8_blit_line (x0+12, x1, y0+4, y1, y_buffer, y_stride);
919 bmi = &mi->bmi[8];
921 x1 = x0 + 4 + (mv->col >> 3);
922 y1 = y0 +12 + (mv->row >> 3);
924 constrain_line (x0+4, &x1, y0+12, &y1, width, height);
925 vp8_blit_line (x0+4, x1, y0+12, y1, y_buffer, y_stride);
927 bmi = &mi->bmi[10];
929 x1 = x0 +12 + (mv->col >> 3);
930 y1 = y0 +12 + (mv->row >> 3);
932 constrain_line (x0+12, &x1, y0+12, &y1, width, height);
933 vp8_blit_line (x0+12, x1, y0+12, y1, y_buffer, y_stride);
934 break;
936 default :
938 B_MODE_INFO *bmi = mi->bmi;
939 int bx0, by0;
941 for (by0 = y0; by0 < (y0+16); by0 += 4)
943 for (bx0 = x0; bx0 < (x0+16); bx0 += 4)
945 MV *mv = &bmi->mv.as_mv;
947 x1 = bx0 + 2 + (mv->col >> 3);
948 y1 = by0 + 2 + (mv->row >> 3);
950 constrain_line (bx0+2, &x1, by0+2, &y1, width, height);
951 vp8_blit_line (bx0+2, x1, by0+2, y1, y_buffer, y_stride);
953 bmi++;
959 else if (mi->mbmi.mode >= NEARESTMV)
961 MV *mv = &mi->mbmi.mv.as_mv;
962 const int lx0 = x0 + 8;
963 const int ly0 = y0 + 8;
965 x1 = lx0 + (mv->col >> 3);
966 y1 = ly0 + (mv->row >> 3);
968 if (x1 != lx0 && y1 != ly0)
970 constrain_line (lx0, &x1, ly0-1, &y1, width, height);
971 vp8_blit_line (lx0, x1, ly0-1, y1, y_buffer, y_stride);
973 constrain_line (lx0, &x1, ly0+1, &y1, width, height);
974 vp8_blit_line (lx0, x1, ly0+1, y1, y_buffer, y_stride);
976 else
977 vp8_blit_line (lx0, x1, ly0, y1, y_buffer, y_stride);
980 mi++;
982 mi++;
986 /* Color in block modes */
987 if ((flags & VP8D_DEBUG_CLR_BLK_MODES)
988 && (ppflags->display_mb_modes_flag || ppflags->display_b_modes_flag))
990 int y, x;
991 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
992 int width = post->y_width;
993 int height = post->y_height;
994 unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
995 unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
996 unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
997 int y_stride = oci->post_proc_buffer.y_stride;
998 MODE_INFO *mi = oci->mi;
1000 for (y = 0; y < height; y += 16)
1002 for (x = 0; x < width; x += 16)
1004 int Y = 0, U = 0, V = 0;
1006 if (mi->mbmi.mode == B_PRED &&
1007 ((ppflags->display_mb_modes_flag & B_PRED) || ppflags->display_b_modes_flag))
1009 int by, bx;
1010 unsigned char *yl, *ul, *vl;
1011 B_MODE_INFO *bmi = mi->bmi;
1013 yl = y_ptr + x;
1014 ul = u_ptr + (x>>1);
1015 vl = v_ptr + (x>>1);
1017 for (by = 0; by < 16; by += 4)
1019 for (bx = 0; bx < 16; bx += 4)
1021 if ((ppflags->display_b_modes_flag & (1<<mi->mbmi.mode))
1022 || (ppflags->display_mb_modes_flag & B_PRED))
1024 Y = B_PREDICTION_MODE_colors[bmi->mode][0];
1025 U = B_PREDICTION_MODE_colors[bmi->mode][1];
1026 V = B_PREDICTION_MODE_colors[bmi->mode][2];
1028 POSTPROC_INVOKE(RTCD_VTABLE(oci), blend_b)
1029 (yl+bx, ul+(bx>>1), vl+(bx>>1), Y, U, V, 0xc000, y_stride);
1031 bmi++;
1034 yl += y_stride*4;
1035 ul += y_stride*1;
1036 vl += y_stride*1;
1039 else if (ppflags->display_mb_modes_flag & (1<<mi->mbmi.mode))
1041 Y = MB_PREDICTION_MODE_colors[mi->mbmi.mode][0];
1042 U = MB_PREDICTION_MODE_colors[mi->mbmi.mode][1];
1043 V = MB_PREDICTION_MODE_colors[mi->mbmi.mode][2];
1045 POSTPROC_INVOKE(RTCD_VTABLE(oci), blend_mb_inner)
1046 (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1049 mi++;
1051 y_ptr += y_stride*16;
1052 u_ptr += y_stride*4;
1053 v_ptr += y_stride*4;
1055 mi++;
1059 /* Color in frame reference blocks */
1060 if ((flags & VP8D_DEBUG_CLR_FRM_REF_BLKS) && ppflags->display_ref_frame_flag)
1062 int y, x;
1063 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
1064 int width = post->y_width;
1065 int height = post->y_height;
1066 unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
1067 unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
1068 unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
1069 int y_stride = oci->post_proc_buffer.y_stride;
1070 MODE_INFO *mi = oci->mi;
1072 for (y = 0; y < height; y += 16)
1074 for (x = 0; x < width; x +=16)
1076 int Y = 0, U = 0, V = 0;
1078 if (ppflags->display_ref_frame_flag & (1<<mi->mbmi.ref_frame))
1080 Y = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][0];
1081 U = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][1];
1082 V = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][2];
1084 POSTPROC_INVOKE(RTCD_VTABLE(oci), blend_mb_outer)
1085 (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1088 mi++;
1090 y_ptr += y_stride*16;
1091 u_ptr += y_stride*4;
1092 v_ptr += y_stride*4;
1094 mi++;
1097 #endif
1099 *dest = oci->post_proc_buffer;
1101 /* handle problem with extending borders */
1102 dest->y_width = oci->Width;
1103 dest->y_height = oci->Height;
1104 dest->uv_height = dest->y_height / 2;
1105 return 0;