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_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"
18
19 #include <math.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22
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)
27
28 /* global constants */
29 #if CONFIG_POSTPROC_VISUALIZER
30 static const unsigned char MB_PREDICTION_MODE_colors[MB_MODE_COUNT][3] =
31 {
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 */
42 };
43
44 static const unsigned char B_PREDICTION_MODE_colors[B_MODE_COUNT][3] =
45 {
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 */
60 };
61
62 static const unsigned char MV_REFERENCE_FRAME_colors[MAX_REF_FRAMES][3] =
63 {
64 { RGB_TO_YUV(0x00ff00) }, /* Blue */
65 { RGB_TO_YUV(0x0000ff) }, /* Green */
66 { RGB_TO_YUV(0xffff00) }, /* Yellow */
67 { RGB_TO_YUV(0xff0000) }, /* Red */
68 };
69 #endif
70
71 static const short kernel5[] =
72 {
73 1, 1, 4, 1, 1
74 };
75
76 const short vp8_rv[] =
77 {
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,
122 };
123
124
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 /***********************************************************************************************************
128 */
vp8_post_proc_down_and_across_c(unsigned char * src_ptr,unsigned char * dst_ptr,int src_pixels_per_line,int dst_pixels_per_line,int rows,int cols,int flimit)129 void vp8_post_proc_down_and_across_c
130 (
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
138 )
139 {
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;
148
149 for (row = 0; row < rows; row++)
150 {
151 /* post_proc_down for one row */
152 p_src = src_ptr;
153 p_dst = dst_ptr;
154
155 for (col = 0; col < cols; col++)
156 {
157
158 int kernel = 4;
159 int v = p_src[col];
160
161 for (i = -2; i <= 2; i++)
162 {
163 if (abs(v - p_src[col+i*pitch]) > flimit)
164 goto down_skip_convolve;
165
166 kernel += kernel5[2+i] * p_src[col+i*pitch];
167 }
168
169 v = (kernel >> 3);
170 down_skip_convolve:
171 p_dst[col] = v;
172 }
173
174 /* now post_proc_across */
175 p_src = dst_ptr;
176 p_dst = dst_ptr;
177
178 for (i = 0; i < 8; i++)
179 d[i] = p_src[i];
180
181 for (col = 0; col < cols; col++)
182 {
183 int kernel = 4;
184 v = p_src[col];
185
186 d[col&7] = v;
187
188 for (i = -2; i <= 2; i++)
189 {
190 if (abs(v - p_src[col+i]) > flimit)
191 goto across_skip_convolve;
192
193 kernel += kernel5[2+i] * p_src[col+i];
194 }
195
196 d[col&7] = (kernel >> 3);
197 across_skip_convolve:
198
199 if (col >= 2)
200 p_dst[col-2] = d[(col-2)&7];
201 }
202
203 /* handle the last two pixels */
204 p_dst[col-2] = d[(col-2)&7];
205 p_dst[col-1] = d[(col-1)&7];
206
207
208 /* next row */
209 src_ptr += pitch;
210 dst_ptr += pitch;
211 }
212 }
213
q2mbl(int x)214 static int q2mbl(int x)
215 {
216 if (x < 20) x = 20;
217
218 x = 50 + (x - 50) * 10 / 8;
219 return x * x / 3;
220 }
vp8_mbpost_proc_across_ip_c(unsigned char * src,int pitch,int rows,int cols,int flimit)221 void vp8_mbpost_proc_across_ip_c(unsigned char *src, int pitch, int rows, int cols, int flimit)
222 {
223 int r, c, i;
224
225 unsigned char *s = src;
226 unsigned char d[16];
227
228
229 for (r = 0; r < rows; r++)
230 {
231 int sumsq = 0;
232 int sum = 0;
233
234 for (i = -8; i <= 6; i++)
235 {
236 sumsq += s[i] * s[i];
237 sum += s[i];
238 d[i+8] = 0;
239 }
240
241 for (c = 0; c < cols + 8; c++)
242 {
243 int x = s[c+7] - s[c-8];
244 int y = s[c+7] + s[c-8];
245
246 sum += x;
247 sumsq += x * y;
248
249 d[c&15] = s[c];
250
251 if (sumsq * 15 - sum * sum < flimit)
252 {
253 d[c&15] = (8 + sum + s[c]) >> 4;
254 }
255
256 s[c-8] = d[(c-8)&15];
257 }
258
259 s += pitch;
260 }
261 }
262
263
264
265
266
vp8_mbpost_proc_down_c(unsigned char * dst,int pitch,int rows,int cols,int flimit)267 void vp8_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols, int flimit)
268 {
269 int r, c, i;
270 const short *rv3 = &vp8_rv[63&rand()];
271
272 for (c = 0; c < cols; c++)
273 {
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);
279
280 for (i = -8; i <= 6; i++)
281 {
282 sumsq += s[i*pitch] * s[i*pitch];
283 sum += s[i*pitch];
284 }
285
286 for (r = 0; r < rows + 8; r++)
287 {
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];
291
292 if (sumsq * 15 - sum * sum < flimit)
293 {
294 d[r&15] = (rv2[r&127] + sum + s[0]) >> 4;
295 }
296
297 s[-8*pitch] = d[(r-8)&15];
298 s += pitch;
299 }
300 }
301 }
302
303
vp8_deblock_and_de_macro_block(YV12_BUFFER_CONFIG * source,YV12_BUFFER_CONFIG * post,int q,int low_var_thresh,int flag,vp8_postproc_rtcd_vtable_t * rtcd)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)
310 {
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;
315
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, q2mbl(q));
318 POSTPROC_INVOKE(rtcd, down)(post->y_buffer, post->y_stride, post->y_height, post->y_width, q2mbl(q));
319
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);
322
323 }
324
vp8_deblock(YV12_BUFFER_CONFIG * source,YV12_BUFFER_CONFIG * post,int q,int low_var_thresh,int flag,vp8_postproc_rtcd_vtable_t * rtcd)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)
331 {
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;
336
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);
340 }
341
vp8_de_noise(YV12_BUFFER_CONFIG * source,YV12_BUFFER_CONFIG * post,int q,int low_var_thresh,int flag,vp8_postproc_rtcd_vtable_t * rtcd)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)
348 {
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;
354
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);
377
378 }
379
vp8_gaussian(double sigma,double mu,double x)380 double vp8_gaussian(double sigma, double mu, double x)
381 {
382 return 1 / (sigma * sqrt(2.0 * 3.14159265)) *
383 (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma)));
384 }
385
386 extern void (*vp8_clear_system_state)(void);
387
388
fillrd(struct postproc_state * state,int q,int a)389 static void fillrd(struct postproc_state *state, int q, int a)
390 {
391 char char_dist[300];
392
393 double sigma;
394 int ai = a, qi = q, i;
395
396 vp8_clear_system_state();
397
398
399 sigma = ai + .5 + .6 * (63 - qi) / 63.0;
400
401 /* set up a lookup table of 256 entries that matches
402 * a gaussian distribution with sigma determined by q.
403 */
404 {
405 double i;
406 int next, j;
407
408 next = 0;
409
410 for (i = -32; i < 32; i++)
411 {
412 int a = (int)(.5 + 256 * vp8_gaussian(sigma, 0, i));
413
414 if (a)
415 {
416 for (j = 0; j < a; j++)
417 {
418 char_dist[next+j] = (char) i;
419 }
420
421 next = next + j;
422 }
423
424 }
425
426 for (next = next; next < 256; next++)
427 char_dist[next] = 0;
428
429 }
430
431 for (i = 0; i < 3072; i++)
432 {
433 state->noise[i] = char_dist[rand() & 0xff];
434 }
435
436 for (i = 0; i < 16; i++)
437 {
438 state->blackclamp[i] = -char_dist[0];
439 state->whiteclamp[i] = -char_dist[0];
440 state->bothclamp[i] = -2 * char_dist[0];
441 }
442
443 state->last_q = q;
444 state->last_noise = a;
445 }
446
447 /****************************************************************************
448 *
449 * ROUTINE : plane_add_noise_c
450 *
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
458 *
459 * OUTPUTS : None.
460 *
461 * RETURNS : void.
462 *
463 * FUNCTION : adds gaussian noise to a plane of pixels
464 *
465 * SPECIAL NOTES : None.
466 *
467 ****************************************************************************/
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)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)
473 {
474 unsigned int i, j;
475
476 for (i = 0; i < Height; i++)
477 {
478 unsigned char *Pos = Start + i * Pitch;
479 char *Ref = (char *)(noise + (rand() & 0xff));
480
481 for (j = 0; j < Width; j++)
482 {
483 if (Pos[j] < blackclamp[0])
484 Pos[j] = blackclamp[0];
485
486 if (Pos[j] > 255 + whiteclamp[0])
487 Pos[j] = 255 + whiteclamp[0];
488
489 Pos[j] += Ref[j];
490 }
491 }
492 }
493
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.
497 */
vp8_blend_mb_inner_c(unsigned char * y,unsigned char * u,unsigned char * v,int y1,int u1,int v1,int alpha,int stride)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)
500 {
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);
505
506 y += 2*stride + 2;
507 for (i = 0; i < 12; i++)
508 {
509 for (j = 0; j < 12; j++)
510 {
511 y[j] = (y[j]*alpha + y1_const)>>16;
512 }
513 y += stride;
514 }
515
516 stride >>= 1;
517
518 u += stride + 1;
519 v += stride + 1;
520
521 for (i = 0; i < 6; i++)
522 {
523 for (j = 0; j < 6; j++)
524 {
525 u[j] = (u[j]*alpha + u1_const)>>16;
526 v[j] = (v[j]*alpha + v1_const)>>16;
527 }
528 u += stride;
529 v += stride;
530 }
531 }
532
533 /* Blend only the edge of the macro block. Leave center
534 * unblended to allow for other visualizations to be layered.
535 */
vp8_blend_mb_outer_c(unsigned char * y,unsigned char * u,unsigned char * v,int y1,int u1,int v1,int alpha,int stride)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)
538 {
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);
543
544 for (i = 0; i < 2; i++)
545 {
546 for (j = 0; j < 16; j++)
547 {
548 y[j] = (y[j]*alpha + y1_const)>>16;
549 }
550 y += stride;
551 }
552
553 for (i = 0; i < 12; i++)
554 {
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;
560 }
561
562 for (i = 0; i < 2; i++)
563 {
564 for (j = 0; j < 16; j++)
565 {
566 y[j] = (y[j]*alpha + y1_const)>>16;
567 }
568 y += stride;
569 }
570
571 stride >>= 1;
572
573 for (j = 0; j < 8; j++)
574 {
575 u[j] = (u[j]*alpha + u1_const)>>16;
576 v[j] = (v[j]*alpha + v1_const)>>16;
577 }
578 u += stride;
579 v += stride;
580
581 for (i = 0; i < 6; i++)
582 {
583 u[0] = (u[0]*alpha + u1_const)>>16;
584 v[0] = (v[0]*alpha + v1_const)>>16;
585
586 u[7] = (u[7]*alpha + u1_const)>>16;
587 v[7] = (v[7]*alpha + v1_const)>>16;
588
589 u += stride;
590 v += stride;
591 }
592
593 for (j = 0; j < 8; j++)
594 {
595 u[j] = (u[j]*alpha + u1_const)>>16;
596 v[j] = (v[j]*alpha + v1_const)>>16;
597 }
598 }
599
vp8_blend_b_c(unsigned char * y,unsigned char * u,unsigned char * v,int y1,int u1,int v1,int alpha,int stride)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)
602 {
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);
607
608 for (i = 0; i < 4; i++)
609 {
610 for (j = 0; j < 4; j++)
611 {
612 y[j] = (y[j]*alpha + y1_const)>>16;
613 }
614 y += stride;
615 }
616
617 stride >>= 1;
618
619 for (i = 0; i < 2; i++)
620 {
621 for (j = 0; j < 2; j++)
622 {
623 u[j] = (u[j]*alpha + u1_const)>>16;
624 v[j] = (v[j]*alpha + v1_const)>>16;
625 }
626 u += stride;
627 v += stride;
628 }
629 }
630
constrain_line(int x0,int * x1,int y0,int * y1,int width,int height)631 static void constrain_line (int x0, int *x1, int y0, int *y1, int width, int height)
632 {
633 int dx;
634 int dy;
635
636 if (*x1 > width)
637 {
638 dx = *x1 - x0;
639 dy = *y1 - y0;
640
641 *x1 = width;
642 if (dx)
643 *y1 = ((width-x0)*dy)/dx + y0;
644 }
645 if (*x1 < 0)
646 {
647 dx = *x1 - x0;
648 dy = *y1 - y0;
649
650 *x1 = 0;
651 if (dx)
652 *y1 = ((0-x0)*dy)/dx + y0;
653 }
654 if (*y1 > height)
655 {
656 dx = *x1 - x0;
657 dy = *y1 - y0;
658
659 *y1 = height;
660 if (dy)
661 *x1 = ((height-y0)*dx)/dy + x0;
662 }
663 if (*y1 < 0)
664 {
665 dx = *x1 - x0;
666 dy = *y1 - y0;
667
668 *y1 = 0;
669 if (dy)
670 *x1 = ((0-y0)*dx)/dy + x0;
671 }
672 }
673
674
675 #if CONFIG_RUNTIME_CPU_DETECT
676 #define RTCD_VTABLE(oci) (&(oci)->rtcd.postproc)
677 #else
678 #define RTCD_VTABLE(oci) NULL
679 #endif
680
vp8_post_proc_frame(VP8_COMMON * oci,YV12_BUFFER_CONFIG * dest,vp8_ppflags_t * ppflags)681 int vp8_post_proc_frame(VP8_COMMON *oci, YV12_BUFFER_CONFIG *dest, vp8_ppflags_t *ppflags)
682 {
683 int q = oci->filter_level * 10 / 6;
684 int flags = ppflags->post_proc_flag;
685 int deblock_level = ppflags->deblocking_level;
686 int noise_level = ppflags->noise_level;
687
688 if (!oci->frame_to_show)
689 return -1;
690
691 if (q > 63)
692 q = 63;
693
694 if (!flags)
695 {
696 *dest = *oci->frame_to_show;
697
698 /* handle problem with extending borders */
699 dest->y_width = oci->Width;
700 dest->y_height = oci->Height;
701 dest->uv_height = dest->y_height / 2;
702 return 0;
703
704 }
705
706 #if ARCH_X86||ARCH_X86_64
707 vpx_reset_mmx_state();
708 #endif
709
710 if (flags & VP8D_DEMACROBLOCK)
711 {
712 vp8_deblock_and_de_macro_block(oci->frame_to_show, &oci->post_proc_buffer,
713 q + (deblock_level - 5) * 10, 1, 0, RTCD_VTABLE(oci));
714 }
715 else if (flags & VP8D_DEBLOCK)
716 {
717 vp8_deblock(oci->frame_to_show, &oci->post_proc_buffer,
718 q, 1, 0, RTCD_VTABLE(oci));
719 }
720 else
721 {
722 vp8_yv12_copy_frame_ptr(oci->frame_to_show, &oci->post_proc_buffer);
723 }
724
725 if (flags & VP8D_ADDNOISE)
726 {
727 if (oci->postproc_state.last_q != q
728 || oci->postproc_state.last_noise != noise_level)
729 {
730 fillrd(&oci->postproc_state, 63 - q, noise_level);
731 }
732
733 POSTPROC_INVOKE(RTCD_VTABLE(oci), addnoise)
734 (oci->post_proc_buffer.y_buffer,
735 oci->postproc_state.noise,
736 oci->postproc_state.blackclamp,
737 oci->postproc_state.whiteclamp,
738 oci->postproc_state.bothclamp,
739 oci->post_proc_buffer.y_width, oci->post_proc_buffer.y_height,
740 oci->post_proc_buffer.y_stride);
741 }
742
743 #if CONFIG_POSTPROC_VISUALIZER
744 if (flags & VP8D_DEBUG_TXT_FRAME_INFO)
745 {
746 char message[512];
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);
755 }
756
757 if (flags & VP8D_DEBUG_TXT_MBLK_MODES)
758 {
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;
766
767 y_ptr = post->y_buffer + 4 * post->y_stride + 4;
768
769 /* vp8_filter each macro block */
770 for (i = 0; i < mb_rows; i++)
771 {
772 for (j = 0; j < mb_cols; j++)
773 {
774 char zz[4];
775
776 sprintf(zz, "%c", mi[mb_index].mbmi.mode + 'a');
777
778 vp8_blit_text(zz, y_ptr, post->y_stride);
779 mb_index ++;
780 y_ptr += 16;
781 }
782
783 mb_index ++; /* border */
784 y_ptr += post->y_stride * 16 - post->y_width;
785
786 }
787 }
788
789 if (flags & VP8D_DEBUG_TXT_DC_DIFF)
790 {
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;
798
799 y_ptr = post->y_buffer + 4 * post->y_stride + 4;
800
801 /* vp8_filter each macro block */
802 for (i = 0; i < mb_rows; i++)
803 {
804 for (j = 0; j < mb_cols; j++)
805 {
806 char zz[4];
807
808 if (oci->frame_type == KEY_FRAME)
809 sprintf(zz, "a");
810 else
811 sprintf(zz, "%c", mi[mb_index].mbmi.dc_diff + '0');
812
813 vp8_blit_text(zz, y_ptr, post->y_stride);
814 mb_index ++;
815 y_ptr += 16;
816 }
817
818 mb_index ++; /* border */
819 y_ptr += post->y_stride * 16 - post->y_width;
820
821 }
822 }
823
824 if (flags & VP8D_DEBUG_TXT_RATE_INFO)
825 {
826 char message[512];
827 sprintf(message, "Bitrate: %10.2f frame_rate: %10.2f ", oci->bitrate, oci->framerate);
828 vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
829 }
830
831 /* Draw motion vectors */
832 if ((flags & VP8D_DEBUG_DRAW_MV) && ppflags->display_mv_flag)
833 {
834 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
835 int width = post->y_width;
836 int height = post->y_height;
837 int mb_cols = width >> 4;
838 unsigned char *y_buffer = oci->post_proc_buffer.y_buffer;
839 int y_stride = oci->post_proc_buffer.y_stride;
840 MODE_INFO *mi = oci->mi;
841 int x0, y0;
842
843 for (y0 = 0; y0 < height; y0 += 16)
844 {
845 for (x0 = 0; x0 < width; x0 += 16)
846 {
847 int x1, y1;
848
849 if (!(ppflags->display_mv_flag & (1<<mi->mbmi.mode)))
850 {
851 mi++;
852 continue;
853 }
854
855 if (mi->mbmi.mode == SPLITMV)
856 {
857 switch (mi->mbmi.partitioning)
858 {
859 case 0 : /* mv_top_bottom */
860 {
861 B_MODE_INFO *bmi = &mi->bmi[0];
862 MV *mv = &bmi->mv.as_mv;
863
864 x1 = x0 + 8 + (mv->col >> 3);
865 y1 = y0 + 4 + (mv->row >> 3);
866
867 constrain_line (x0+8, &x1, y0+4, &y1, width, height);
868 vp8_blit_line (x0+8, x1, y0+4, y1, y_buffer, y_stride);
869
870 bmi = &mi->bmi[8];
871
872 x1 = x0 + 8 + (mv->col >> 3);
873 y1 = y0 +12 + (mv->row >> 3);
874
875 constrain_line (x0+8, &x1, y0+12, &y1, width, height);
876 vp8_blit_line (x0+8, x1, y0+12, y1, y_buffer, y_stride);
877
878 break;
879 }
880 case 1 : /* mv_left_right */
881 {
882 B_MODE_INFO *bmi = &mi->bmi[0];
883 MV *mv = &bmi->mv.as_mv;
884
885 x1 = x0 + 4 + (mv->col >> 3);
886 y1 = y0 + 8 + (mv->row >> 3);
887
888 constrain_line (x0+4, &x1, y0+8, &y1, width, height);
889 vp8_blit_line (x0+4, x1, y0+8, y1, y_buffer, y_stride);
890
891 bmi = &mi->bmi[2];
892
893 x1 = x0 +12 + (mv->col >> 3);
894 y1 = y0 + 8 + (mv->row >> 3);
895
896 constrain_line (x0+12, &x1, y0+8, &y1, width, height);
897 vp8_blit_line (x0+12, x1, y0+8, y1, y_buffer, y_stride);
898
899 break;
900 }
901 case 2 : /* mv_quarters */
902 {
903 B_MODE_INFO *bmi = &mi->bmi[0];
904 MV *mv = &bmi->mv.as_mv;
905
906 x1 = x0 + 4 + (mv->col >> 3);
907 y1 = y0 + 4 + (mv->row >> 3);
908
909 constrain_line (x0+4, &x1, y0+4, &y1, width, height);
910 vp8_blit_line (x0+4, x1, y0+4, y1, y_buffer, y_stride);
911
912 bmi = &mi->bmi[2];
913
914 x1 = x0 +12 + (mv->col >> 3);
915 y1 = y0 + 4 + (mv->row >> 3);
916
917 constrain_line (x0+12, &x1, y0+4, &y1, width, height);
918 vp8_blit_line (x0+12, x1, y0+4, y1, y_buffer, y_stride);
919
920 bmi = &mi->bmi[8];
921
922 x1 = x0 + 4 + (mv->col >> 3);
923 y1 = y0 +12 + (mv->row >> 3);
924
925 constrain_line (x0+4, &x1, y0+12, &y1, width, height);
926 vp8_blit_line (x0+4, x1, y0+12, y1, y_buffer, y_stride);
927
928 bmi = &mi->bmi[10];
929
930 x1 = x0 +12 + (mv->col >> 3);
931 y1 = y0 +12 + (mv->row >> 3);
932
933 constrain_line (x0+12, &x1, y0+12, &y1, width, height);
934 vp8_blit_line (x0+12, x1, y0+12, y1, y_buffer, y_stride);
935 break;
936 }
937 default :
938 {
939 B_MODE_INFO *bmi = mi->bmi;
940 int bx0, by0;
941
942 for (by0 = y0; by0 < (y0+16); by0 += 4)
943 {
944 for (bx0 = x0; bx0 < (x0+16); bx0 += 4)
945 {
946 MV *mv = &bmi->mv.as_mv;
947
948 x1 = bx0 + 2 + (mv->col >> 3);
949 y1 = by0 + 2 + (mv->row >> 3);
950
951 constrain_line (bx0+2, &x1, by0+2, &y1, width, height);
952 vp8_blit_line (bx0+2, x1, by0+2, y1, y_buffer, y_stride);
953
954 bmi++;
955 }
956 }
957 }
958 }
959 }
960 else if (mi->mbmi.mode >= NEARESTMV)
961 {
962 MV *mv = &mi->mbmi.mv.as_mv;
963 const int lx0 = x0 + 8;
964 const int ly0 = y0 + 8;
965
966 x1 = lx0 + (mv->col >> 3);
967 y1 = ly0 + (mv->row >> 3);
968
969 if (x1 != lx0 && y1 != ly0)
970 {
971 constrain_line (lx0, &x1, ly0-1, &y1, width, height);
972 vp8_blit_line (lx0, x1, ly0-1, y1, y_buffer, y_stride);
973
974 constrain_line (lx0, &x1, ly0+1, &y1, width, height);
975 vp8_blit_line (lx0, x1, ly0+1, y1, y_buffer, y_stride);
976 }
977 else
978 vp8_blit_line (lx0, x1, ly0, y1, y_buffer, y_stride);
979 }
980
981 mi++;
982 }
983 mi++;
984 }
985 }
986
987 /* Color in block modes */
988 if ((flags & VP8D_DEBUG_CLR_BLK_MODES)
989 && (ppflags->display_mb_modes_flag || ppflags->display_b_modes_flag))
990 {
991 int y, x;
992 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
993 int width = post->y_width;
994 int height = post->y_height;
995 unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
996 unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
997 unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
998 int y_stride = oci->post_proc_buffer.y_stride;
999 MODE_INFO *mi = oci->mi;
1000
1001 for (y = 0; y < height; y += 16)
1002 {
1003 for (x = 0; x < width; x += 16)
1004 {
1005 int Y = 0, U = 0, V = 0;
1006
1007 if (mi->mbmi.mode == B_PRED &&
1008 ((ppflags->display_mb_modes_flag & B_PRED) || ppflags->display_b_modes_flag))
1009 {
1010 int by, bx;
1011 unsigned char *yl, *ul, *vl;
1012 B_MODE_INFO *bmi = mi->bmi;
1013
1014 yl = y_ptr + x;
1015 ul = u_ptr + (x>>1);
1016 vl = v_ptr + (x>>1);
1017
1018 for (by = 0; by < 16; by += 4)
1019 {
1020 for (bx = 0; bx < 16; bx += 4)
1021 {
1022 if ((ppflags->display_b_modes_flag & (1<<mi->mbmi.mode))
1023 || (ppflags->display_mb_modes_flag & B_PRED))
1024 {
1025 Y = B_PREDICTION_MODE_colors[bmi->mode][0];
1026 U = B_PREDICTION_MODE_colors[bmi->mode][1];
1027 V = B_PREDICTION_MODE_colors[bmi->mode][2];
1028
1029 POSTPROC_INVOKE(RTCD_VTABLE(oci), blend_b)
1030 (yl+bx, ul+(bx>>1), vl+(bx>>1), Y, U, V, 0xc000, y_stride);
1031 }
1032 bmi++;
1033 }
1034
1035 yl += y_stride*4;
1036 ul += y_stride*1;
1037 vl += y_stride*1;
1038 }
1039 }
1040 else if (ppflags->display_mb_modes_flag & (1<<mi->mbmi.mode))
1041 {
1042 Y = MB_PREDICTION_MODE_colors[mi->mbmi.mode][0];
1043 U = MB_PREDICTION_MODE_colors[mi->mbmi.mode][1];
1044 V = MB_PREDICTION_MODE_colors[mi->mbmi.mode][2];
1045
1046 POSTPROC_INVOKE(RTCD_VTABLE(oci), blend_mb_inner)
1047 (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1048 }
1049
1050 mi++;
1051 }
1052 y_ptr += y_stride*16;
1053 u_ptr += y_stride*4;
1054 v_ptr += y_stride*4;
1055
1056 mi++;
1057 }
1058 }
1059
1060 /* Color in frame reference blocks */
1061 if ((flags & VP8D_DEBUG_CLR_FRM_REF_BLKS) && ppflags->display_ref_frame_flag)
1062 {
1063 int y, x;
1064 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
1065 int width = post->y_width;
1066 int height = post->y_height;
1067 unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
1068 unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
1069 unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
1070 int y_stride = oci->post_proc_buffer.y_stride;
1071 MODE_INFO *mi = oci->mi;
1072
1073 for (y = 0; y < height; y += 16)
1074 {
1075 for (x = 0; x < width; x +=16)
1076 {
1077 int Y = 0, U = 0, V = 0;
1078
1079 if (ppflags->display_ref_frame_flag & (1<<mi->mbmi.ref_frame))
1080 {
1081 Y = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][0];
1082 U = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][1];
1083 V = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][2];
1084
1085 POSTPROC_INVOKE(RTCD_VTABLE(oci), blend_mb_outer)
1086 (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1087 }
1088
1089 mi++;
1090 }
1091 y_ptr += y_stride*16;
1092 u_ptr += y_stride*4;
1093 v_ptr += y_stride*4;
1094
1095 mi++;
1096 }
1097 }
1098 #endif
1099
1100 *dest = oci->post_proc_buffer;
1101
1102 /* handle problem with extending borders */
1103 dest->y_width = oci->Width;
1104 dest->y_height = oci->Height;
1105 dest->uv_height = dest->y_height / 2;
1106 return 0;
1107 }
1108