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
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[MB_MODE_COUNT][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
70 static const short kernel5[] =
71 {
72 1, 1, 4, 1, 1
73 };
74
75 const short vp8_rv[] =
76 {
77 8, 5, 2, 2, 8, 12, 4, 9, 8, 3,
78 0, 3, 9, 0, 0, 0, 8, 3, 14, 4,
79 10, 1, 11, 14, 1, 14, 9, 6, 12, 11,
80 8, 6, 10, 0, 0, 8, 9, 0, 3, 14,
81 8, 11, 13, 4, 2, 9, 0, 3, 9, 6,
82 1, 2, 3, 14, 13, 1, 8, 2, 9, 7,
83 3, 3, 1, 13, 13, 6, 6, 5, 2, 7,
84 11, 9, 11, 8, 7, 3, 2, 0, 13, 13,
85 14, 4, 12, 5, 12, 10, 8, 10, 13, 10,
86 4, 14, 4, 10, 0, 8, 11, 1, 13, 7,
87 7, 14, 6, 14, 13, 2, 13, 5, 4, 4,
88 0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
89 8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
90 3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
91 3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
92 13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
93 5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
94 9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
95 4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
96 3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
97 11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
98 5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
99 0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
100 10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
101 4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
102 0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
103 8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
104 3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
105 3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
106 13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
107 5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
108 9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
109 4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
110 3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
111 11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
112 5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
113 0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
114 10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
115 4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
116 3, 8, 3, 7, 8, 5, 11, 4, 12, 3,
117 11, 9, 14, 8, 14, 13, 4, 3, 1, 2,
118 14, 6, 5, 4, 4, 11, 4, 6, 2, 1,
119 5, 8, 8, 12, 13, 5, 14, 10, 12, 13,
120 0, 9, 5, 5, 11, 10, 13, 9, 10, 13,
121 };
122
123
124 extern void vp8_blit_text(const char *msg, unsigned char *address, const int pitch);
125 extern void vp8_blit_line(int x0, int x1, int y0, int y1, unsigned char *image, const int pitch);
126 /***********************************************************************************************************
127 */
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)128 void vp8_post_proc_down_and_across_c
129 (
130 unsigned char *src_ptr,
131 unsigned char *dst_ptr,
132 int src_pixels_per_line,
133 int dst_pixels_per_line,
134 int rows,
135 int cols,
136 int flimit
137 )
138 {
139 unsigned char *p_src, *p_dst;
140 int row;
141 int col;
142 int i;
143 int v;
144 int pitch = src_pixels_per_line;
145 unsigned char d[8];
146 (void)dst_pixels_per_line;
147
148 for (row = 0; row < rows; row++)
149 {
150 /* post_proc_down for one row */
151 p_src = src_ptr;
152 p_dst = dst_ptr;
153
154 for (col = 0; col < cols; col++)
155 {
156
157 int kernel = 4;
158 int v = p_src[col];
159
160 for (i = -2; i <= 2; i++)
161 {
162 if (abs(v - p_src[col+i*pitch]) > flimit)
163 goto down_skip_convolve;
164
165 kernel += kernel5[2+i] * p_src[col+i*pitch];
166 }
167
168 v = (kernel >> 3);
169 down_skip_convolve:
170 p_dst[col] = v;
171 }
172
173 /* now post_proc_across */
174 p_src = dst_ptr;
175 p_dst = dst_ptr;
176
177 for (i = 0; i < 8; i++)
178 d[i] = p_src[i];
179
180 for (col = 0; col < cols; col++)
181 {
182 int kernel = 4;
183 v = p_src[col];
184
185 d[col&7] = v;
186
187 for (i = -2; i <= 2; i++)
188 {
189 if (abs(v - p_src[col+i]) > flimit)
190 goto across_skip_convolve;
191
192 kernel += kernel5[2+i] * p_src[col+i];
193 }
194
195 d[col&7] = (kernel >> 3);
196 across_skip_convolve:
197
198 if (col >= 2)
199 p_dst[col-2] = d[(col-2)&7];
200 }
201
202 /* handle the last two pixels */
203 p_dst[col-2] = d[(col-2)&7];
204 p_dst[col-1] = d[(col-1)&7];
205
206
207 /* next row */
208 src_ptr += pitch;
209 dst_ptr += pitch;
210 }
211 }
212
vp8_q2mbl(int x)213 int vp8_q2mbl(int x)
214 {
215 if (x < 20) x = 20;
216
217 x = 50 + (x - 50) * 10 / 8;
218 return x * x / 3;
219 }
vp8_mbpost_proc_across_ip_c(unsigned char * src,int pitch,int rows,int cols,int flimit)220 void vp8_mbpost_proc_across_ip_c(unsigned char *src, int pitch, int rows, int cols, int flimit)
221 {
222 int r, c, i;
223
224 unsigned char *s = src;
225 unsigned char d[16];
226
227
228 for (r = 0; r < rows; r++)
229 {
230 int sumsq = 0;
231 int sum = 0;
232
233 for (i = -8; i <= 6; i++)
234 {
235 sumsq += s[i] * s[i];
236 sum += s[i];
237 d[i+8] = 0;
238 }
239
240 for (c = 0; c < cols + 8; c++)
241 {
242 int x = s[c+7] - s[c-8];
243 int y = s[c+7] + s[c-8];
244
245 sum += x;
246 sumsq += x * y;
247
248 d[c&15] = s[c];
249
250 if (sumsq * 15 - sum * sum < flimit)
251 {
252 d[c&15] = (8 + sum + s[c]) >> 4;
253 }
254
255 s[c-8] = d[(c-8)&15];
256 }
257
258 s += pitch;
259 }
260 }
261
262
263
264
265
vp8_mbpost_proc_down_c(unsigned char * dst,int pitch,int rows,int cols,int flimit)266 void vp8_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols, int flimit)
267 {
268 int r, c, i;
269 const short *rv3 = &vp8_rv[63&rand()];
270
271 for (c = 0; c < cols; c++)
272 {
273 unsigned char *s = &dst[c];
274 int sumsq = 0;
275 int sum = 0;
276 unsigned char d[16];
277 const short *rv2 = rv3 + ((c * 17) & 127);
278
279 for (i = -8; i <= 6; i++)
280 {
281 sumsq += s[i*pitch] * s[i*pitch];
282 sum += s[i*pitch];
283 }
284
285 for (r = 0; r < rows + 8; r++)
286 {
287 sumsq += s[7*pitch] * s[ 7*pitch] - s[-8*pitch] * s[-8*pitch];
288 sum += s[7*pitch] - s[-8*pitch];
289 d[r&15] = s[0];
290
291 if (sumsq * 15 - sum * sum < flimit)
292 {
293 d[r&15] = (rv2[r&127] + sum + s[0]) >> 4;
294 }
295
296 s[-8*pitch] = d[(r-8)&15];
297 s += pitch;
298 }
299 }
300 }
301
302
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)303 static void vp8_deblock_and_de_macro_block(YV12_BUFFER_CONFIG *source,
304 YV12_BUFFER_CONFIG *post,
305 int q,
306 int low_var_thresh,
307 int flag,
308 vp8_postproc_rtcd_vtable_t *rtcd)
309 {
310 double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
311 int ppl = (int)(level + .5);
312 (void) low_var_thresh;
313 (void) flag;
314
315 POSTPROC_INVOKE(rtcd, downacross)(source->y_buffer, post->y_buffer, source->y_stride, post->y_stride, source->y_height, source->y_width, ppl);
316 POSTPROC_INVOKE(rtcd, across)(post->y_buffer, post->y_stride, post->y_height, post->y_width, vp8_q2mbl(q));
317 POSTPROC_INVOKE(rtcd, down)(post->y_buffer, post->y_stride, post->y_height, post->y_width, vp8_q2mbl(q));
318
319 POSTPROC_INVOKE(rtcd, downacross)(source->u_buffer, post->u_buffer, source->uv_stride, post->uv_stride, source->uv_height, source->uv_width, ppl);
320 POSTPROC_INVOKE(rtcd, downacross)(source->v_buffer, post->v_buffer, source->uv_stride, post->uv_stride, source->uv_height, source->uv_width, ppl);
321
322 }
323
vp8_deblock(YV12_BUFFER_CONFIG * source,YV12_BUFFER_CONFIG * post,int q,int low_var_thresh,int flag,vp8_postproc_rtcd_vtable_t * rtcd)324 void vp8_deblock(YV12_BUFFER_CONFIG *source,
325 YV12_BUFFER_CONFIG *post,
326 int q,
327 int low_var_thresh,
328 int flag,
329 vp8_postproc_rtcd_vtable_t *rtcd)
330 {
331 double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
332 int ppl = (int)(level + .5);
333 (void) low_var_thresh;
334 (void) flag;
335
336 POSTPROC_INVOKE(rtcd, downacross)(source->y_buffer, post->y_buffer, source->y_stride, post->y_stride, source->y_height, source->y_width, ppl);
337 POSTPROC_INVOKE(rtcd, downacross)(source->u_buffer, post->u_buffer, source->uv_stride, post->uv_stride, source->uv_height, source->uv_width, ppl);
338 POSTPROC_INVOKE(rtcd, downacross)(source->v_buffer, post->v_buffer, source->uv_stride, post->uv_stride, source->uv_height, source->uv_width, ppl);
339 }
340
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)341 void vp8_de_noise(YV12_BUFFER_CONFIG *source,
342 YV12_BUFFER_CONFIG *post,
343 int q,
344 int low_var_thresh,
345 int flag,
346 vp8_postproc_rtcd_vtable_t *rtcd)
347 {
348 double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
349 int ppl = (int)(level + .5);
350 (void) post;
351 (void) low_var_thresh;
352 (void) flag;
353
354 POSTPROC_INVOKE(rtcd, downacross)(
355 source->y_buffer + 2 * source->y_stride + 2,
356 source->y_buffer + 2 * source->y_stride + 2,
357 source->y_stride,
358 source->y_stride,
359 source->y_height - 4,
360 source->y_width - 4,
361 ppl);
362 POSTPROC_INVOKE(rtcd, downacross)(
363 source->u_buffer + 2 * source->uv_stride + 2,
364 source->u_buffer + 2 * source->uv_stride + 2,
365 source->uv_stride,
366 source->uv_stride,
367 source->uv_height - 4,
368 source->uv_width - 4, ppl);
369 POSTPROC_INVOKE(rtcd, downacross)(
370 source->v_buffer + 2 * source->uv_stride + 2,
371 source->v_buffer + 2 * source->uv_stride + 2,
372 source->uv_stride,
373 source->uv_stride,
374 source->uv_height - 4,
375 source->uv_width - 4, ppl);
376
377 }
378
vp8_gaussian(double sigma,double mu,double x)379 double vp8_gaussian(double sigma, double mu, double x)
380 {
381 return 1 / (sigma * sqrt(2.0 * 3.14159265)) *
382 (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma)));
383 }
384
385 extern void (*vp8_clear_system_state)(void);
386
387
fillrd(struct postproc_state * state,int q,int a)388 static void fillrd(struct postproc_state *state, int q, int a)
389 {
390 char char_dist[300];
391
392 double sigma;
393 int ai = a, qi = q, i;
394
395 vp8_clear_system_state();
396
397
398 sigma = ai + .5 + .6 * (63 - qi) / 63.0;
399
400 /* set up a lookup table of 256 entries that matches
401 * a gaussian distribution with sigma determined by q.
402 */
403 {
404 double i;
405 int next, j;
406
407 next = 0;
408
409 for (i = -32; i < 32; i++)
410 {
411 int a = (int)(.5 + 256 * vp8_gaussian(sigma, 0, i));
412
413 if (a)
414 {
415 for (j = 0; j < a; j++)
416 {
417 char_dist[next+j] = (char) i;
418 }
419
420 next = next + j;
421 }
422
423 }
424
425 for (next = next; next < 256; next++)
426 char_dist[next] = 0;
427
428 }
429
430 for (i = 0; i < 3072; i++)
431 {
432 state->noise[i] = char_dist[rand() & 0xff];
433 }
434
435 for (i = 0; i < 16; i++)
436 {
437 state->blackclamp[i] = -char_dist[0];
438 state->whiteclamp[i] = -char_dist[0];
439 state->bothclamp[i] = -2 * char_dist[0];
440 }
441
442 state->last_q = q;
443 state->last_noise = a;
444 }
445
446 /****************************************************************************
447 *
448 * ROUTINE : plane_add_noise_c
449 *
450 * INPUTS : unsigned char *Start starting address of buffer to add gaussian
451 * noise to
452 * unsigned int Width width of plane
453 * unsigned int Height height of plane
454 * int Pitch distance between subsequent lines of frame
455 * int q quantizer used to determine amount of noise
456 * to add
457 *
458 * OUTPUTS : None.
459 *
460 * RETURNS : void.
461 *
462 * FUNCTION : adds gaussian noise to a plane of pixels
463 *
464 * SPECIAL NOTES : None.
465 *
466 ****************************************************************************/
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)467 void vp8_plane_add_noise_c(unsigned char *Start, char *noise,
468 char blackclamp[16],
469 char whiteclamp[16],
470 char bothclamp[16],
471 unsigned int Width, unsigned int Height, int Pitch)
472 {
473 unsigned int i, j;
474
475 for (i = 0; i < Height; i++)
476 {
477 unsigned char *Pos = Start + i * Pitch;
478 char *Ref = (char *)(noise + (rand() & 0xff));
479
480 for (j = 0; j < Width; j++)
481 {
482 if (Pos[j] < blackclamp[0])
483 Pos[j] = blackclamp[0];
484
485 if (Pos[j] > 255 + whiteclamp[0])
486 Pos[j] = 255 + whiteclamp[0];
487
488 Pos[j] += Ref[j];
489 }
490 }
491 }
492
493 /* Blend the macro block with a solid colored square. Leave the
494 * edges unblended to give distinction to macro blocks in areas
495 * filled with the same color block.
496 */
vp8_blend_mb_inner_c(unsigned char * y,unsigned char * u,unsigned char * v,int y1,int u1,int v1,int alpha,int stride)497 void vp8_blend_mb_inner_c (unsigned char *y, unsigned char *u, unsigned char *v,
498 int y1, int u1, int v1, int alpha, int stride)
499 {
500 int i, j;
501 int y1_const = y1*((1<<16)-alpha);
502 int u1_const = u1*((1<<16)-alpha);
503 int v1_const = v1*((1<<16)-alpha);
504
505 y += 2*stride + 2;
506 for (i = 0; i < 12; i++)
507 {
508 for (j = 0; j < 12; j++)
509 {
510 y[j] = (y[j]*alpha + y1_const)>>16;
511 }
512 y += stride;
513 }
514
515 stride >>= 1;
516
517 u += stride + 1;
518 v += stride + 1;
519
520 for (i = 0; i < 6; i++)
521 {
522 for (j = 0; j < 6; j++)
523 {
524 u[j] = (u[j]*alpha + u1_const)>>16;
525 v[j] = (v[j]*alpha + v1_const)>>16;
526 }
527 u += stride;
528 v += stride;
529 }
530 }
531
532 /* Blend only the edge of the macro block. Leave center
533 * unblended to allow for other visualizations to be layered.
534 */
vp8_blend_mb_outer_c(unsigned char * y,unsigned char * u,unsigned char * v,int y1,int u1,int v1,int alpha,int stride)535 void vp8_blend_mb_outer_c (unsigned char *y, unsigned char *u, unsigned char *v,
536 int y1, int u1, int v1, int alpha, int stride)
537 {
538 int i, j;
539 int y1_const = y1*((1<<16)-alpha);
540 int u1_const = u1*((1<<16)-alpha);
541 int v1_const = v1*((1<<16)-alpha);
542
543 for (i = 0; i < 2; i++)
544 {
545 for (j = 0; j < 16; j++)
546 {
547 y[j] = (y[j]*alpha + y1_const)>>16;
548 }
549 y += stride;
550 }
551
552 for (i = 0; i < 12; i++)
553 {
554 y[0] = (y[0]*alpha + y1_const)>>16;
555 y[1] = (y[1]*alpha + y1_const)>>16;
556 y[14] = (y[14]*alpha + y1_const)>>16;
557 y[15] = (y[15]*alpha + y1_const)>>16;
558 y += stride;
559 }
560
561 for (i = 0; i < 2; i++)
562 {
563 for (j = 0; j < 16; j++)
564 {
565 y[j] = (y[j]*alpha + y1_const)>>16;
566 }
567 y += stride;
568 }
569
570 stride >>= 1;
571
572 for (j = 0; j < 8; j++)
573 {
574 u[j] = (u[j]*alpha + u1_const)>>16;
575 v[j] = (v[j]*alpha + v1_const)>>16;
576 }
577 u += stride;
578 v += stride;
579
580 for (i = 0; i < 6; i++)
581 {
582 u[0] = (u[0]*alpha + u1_const)>>16;
583 v[0] = (v[0]*alpha + v1_const)>>16;
584
585 u[7] = (u[7]*alpha + u1_const)>>16;
586 v[7] = (v[7]*alpha + v1_const)>>16;
587
588 u += stride;
589 v += stride;
590 }
591
592 for (j = 0; j < 8; j++)
593 {
594 u[j] = (u[j]*alpha + u1_const)>>16;
595 v[j] = (v[j]*alpha + v1_const)>>16;
596 }
597 }
598
vp8_blend_b_c(unsigned char * y,unsigned char * u,unsigned char * v,int y1,int u1,int v1,int alpha,int stride)599 void vp8_blend_b_c (unsigned char *y, unsigned char *u, unsigned char *v,
600 int y1, int u1, int v1, int alpha, int stride)
601 {
602 int i, j;
603 int y1_const = y1*((1<<16)-alpha);
604 int u1_const = u1*((1<<16)-alpha);
605 int v1_const = v1*((1<<16)-alpha);
606
607 for (i = 0; i < 4; i++)
608 {
609 for (j = 0; j < 4; j++)
610 {
611 y[j] = (y[j]*alpha + y1_const)>>16;
612 }
613 y += stride;
614 }
615
616 stride >>= 1;
617
618 for (i = 0; i < 2; i++)
619 {
620 for (j = 0; j < 2; j++)
621 {
622 u[j] = (u[j]*alpha + u1_const)>>16;
623 v[j] = (v[j]*alpha + v1_const)>>16;
624 }
625 u += stride;
626 v += stride;
627 }
628 }
629
constrain_line(int x0,int * x1,int y0,int * y1,int width,int height)630 static void constrain_line (int x0, int *x1, int y0, int *y1, int width, int height)
631 {
632 int dx;
633 int dy;
634
635 if (*x1 > width)
636 {
637 dx = *x1 - x0;
638 dy = *y1 - y0;
639
640 *x1 = width;
641 if (dx)
642 *y1 = ((width-x0)*dy)/dx + y0;
643 }
644 if (*x1 < 0)
645 {
646 dx = *x1 - x0;
647 dy = *y1 - y0;
648
649 *x1 = 0;
650 if (dx)
651 *y1 = ((0-x0)*dy)/dx + y0;
652 }
653 if (*y1 > height)
654 {
655 dx = *x1 - x0;
656 dy = *y1 - y0;
657
658 *y1 = height;
659 if (dy)
660 *x1 = ((height-y0)*dx)/dy + x0;
661 }
662 if (*y1 < 0)
663 {
664 dx = *x1 - x0;
665 dy = *y1 - y0;
666
667 *y1 = 0;
668 if (dy)
669 *x1 = ((0-y0)*dx)/dy + x0;
670 }
671 }
672
673
674 #if CONFIG_RUNTIME_CPU_DETECT
675 #define RTCD_VTABLE(oci) (&(oci)->rtcd.postproc)
676 #else
677 #define RTCD_VTABLE(oci) NULL
678 #endif
679
vp8_post_proc_frame(VP8_COMMON * oci,YV12_BUFFER_CONFIG * dest,int deblock_level,int noise_level,int flags)680 int vp8_post_proc_frame(VP8_COMMON *oci, YV12_BUFFER_CONFIG *dest, int deblock_level, int noise_level, int flags)
681 {
682 char message[512];
683 int q = oci->filter_level * 10 / 6;
684
685 if (!oci->frame_to_show)
686 return -1;
687
688 if (q > 63)
689 q = 63;
690
691 if (!flags)
692 {
693 *dest = *oci->frame_to_show;
694
695 /* handle problem with extending borders */
696 dest->y_width = oci->Width;
697 dest->y_height = oci->Height;
698 dest->uv_height = dest->y_height / 2;
699 return 0;
700
701 }
702
703 #if ARCH_X86||ARCH_X86_64
704 vpx_reset_mmx_state();
705 #endif
706
707 if (flags & VP8D_DEMACROBLOCK)
708 {
709 vp8_deblock_and_de_macro_block(oci->frame_to_show, &oci->post_proc_buffer,
710 q + (deblock_level - 5) * 10, 1, 0, RTCD_VTABLE(oci));
711 }
712 else if (flags & VP8D_DEBLOCK)
713 {
714 vp8_deblock(oci->frame_to_show, &oci->post_proc_buffer,
715 q, 1, 0, RTCD_VTABLE(oci));
716 }
717 else
718 {
719 vp8_yv12_copy_frame_ptr(oci->frame_to_show, &oci->post_proc_buffer);
720 }
721
722 if (flags & VP8D_ADDNOISE)
723 {
724 if (oci->postproc_state.last_q != q
725 || oci->postproc_state.last_noise != noise_level)
726 {
727 fillrd(&oci->postproc_state, 63 - q, noise_level);
728 }
729
730 POSTPROC_INVOKE(RTCD_VTABLE(oci), addnoise)
731 (oci->post_proc_buffer.y_buffer,
732 oci->postproc_state.noise,
733 oci->postproc_state.blackclamp,
734 oci->postproc_state.whiteclamp,
735 oci->postproc_state.bothclamp,
736 oci->post_proc_buffer.y_width, oci->post_proc_buffer.y_height,
737 oci->post_proc_buffer.y_stride);
738 }
739
740 if (flags & VP8D_DEBUG_LEVEL1)
741 {
742 sprintf(message, "F%1dG%1dQ%3dF%3dP%d_s%dx%d",
743 (oci->frame_type == KEY_FRAME),
744 oci->refresh_golden_frame,
745 oci->base_qindex,
746 oci->filter_level,
747 flags,
748 oci->mb_cols, oci->mb_rows);
749 vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
750 }
751
752 if (flags & VP8D_DEBUG_LEVEL2)
753 {
754 int i, j;
755 unsigned char *y_ptr;
756 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
757 int mb_rows = post->y_height >> 4;
758 int mb_cols = post->y_width >> 4;
759 int mb_index = 0;
760 MODE_INFO *mi = oci->mi;
761
762 y_ptr = post->y_buffer + 4 * post->y_stride + 4;
763
764 /* vp8_filter each macro block */
765 for (i = 0; i < mb_rows; i++)
766 {
767 for (j = 0; j < mb_cols; j++)
768 {
769 char zz[4];
770
771 sprintf(zz, "%c", mi[mb_index].mbmi.mode + 'a');
772
773 vp8_blit_text(zz, y_ptr, post->y_stride);
774 mb_index ++;
775 y_ptr += 16;
776 }
777
778 mb_index ++; /* border */
779 y_ptr += post->y_stride * 16 - post->y_width;
780
781 }
782 }
783
784 if (flags & VP8D_DEBUG_LEVEL3)
785 {
786 int i, j;
787 unsigned char *y_ptr;
788 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
789 int mb_rows = post->y_height >> 4;
790 int mb_cols = post->y_width >> 4;
791 int mb_index = 0;
792 MODE_INFO *mi = oci->mi;
793
794 y_ptr = post->y_buffer + 4 * post->y_stride + 4;
795
796 /* vp8_filter each macro block */
797 for (i = 0; i < mb_rows; i++)
798 {
799 for (j = 0; j < mb_cols; j++)
800 {
801 char zz[4];
802
803 if (oci->frame_type == KEY_FRAME)
804 sprintf(zz, "a");
805 else
806 sprintf(zz, "%c", mi[mb_index].mbmi.dc_diff + '0');
807
808 vp8_blit_text(zz, y_ptr, post->y_stride);
809 mb_index ++;
810 y_ptr += 16;
811 }
812
813 mb_index ++; /* border */
814 y_ptr += post->y_stride * 16 - post->y_width;
815
816 }
817 }
818
819 if (flags & VP8D_DEBUG_LEVEL4)
820 {
821 sprintf(message, "Bitrate: %10.2f frame_rate: %10.2f ", oci->bitrate, oci->framerate);
822 vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
823 #if 0
824 int i, j;
825 unsigned char *y_ptr;
826 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
827 int mb_rows = post->y_height >> 4;
828 int mb_cols = post->y_width >> 4;
829 int mb_index = 0;
830 MODE_INFO *mi = oci->mi;
831
832 y_ptr = post->y_buffer + 4 * post->y_stride + 4;
833
834 /* vp8_filter each macro block */
835 for (i = 0; i < mb_rows; i++)
836 {
837 for (j = 0; j < mb_cols; j++)
838 {
839 char zz[4];
840
841 sprintf(zz, "%c", mi[mb_index].mbmi.dc_diff + '0');
842 vp8_blit_text(zz, y_ptr, post->y_stride);
843 mb_index ++;
844 y_ptr += 16;
845 }
846
847 mb_index ++; /* border */
848 y_ptr += post->y_stride * 16 - post->y_width;
849
850 }
851
852 #endif
853
854 }
855
856 /* Draw motion vectors */
857 if (flags & VP8D_DEBUG_DRAW_MV)
858 {
859 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
860 int width = post->y_width;
861 int height = post->y_height;
862 int mb_cols = width >> 4;
863 unsigned char *y_buffer = oci->post_proc_buffer.y_buffer;
864 int y_stride = oci->post_proc_buffer.y_stride;
865 MODE_INFO *mi = oci->mi;
866 int x0, y0;
867
868 for (y0 = 0; y0 < height; y0 += 16)
869 {
870 for (x0 = 0; x0 < width; x0 += 16)
871 {
872 int x1, y1;
873
874 if (mi->mbmi.mode == SPLITMV)
875 {
876 switch (mi->mbmi.partitioning)
877 {
878 case 0 : /* mv_top_bottom */
879 {
880 B_MODE_INFO *bmi = &mi->bmi[0];
881 MV *mv = &bmi->mv.as_mv;
882
883 x1 = x0 + 8 + (mv->col >> 3);
884 y1 = y0 + 4 + (mv->row >> 3);
885
886 constrain_line (x0+8, &x1, y0+4, &y1, width, height);
887 vp8_blit_line (x0+8, x1, y0+4, y1, y_buffer, y_stride);
888
889 bmi = &mi->bmi[8];
890
891 x1 = x0 + 8 + (mv->col >> 3);
892 y1 = y0 +12 + (mv->row >> 3);
893
894 constrain_line (x0+8, &x1, y0+12, &y1, width, height);
895 vp8_blit_line (x0+8, x1, y0+12, y1, y_buffer, y_stride);
896
897 break;
898 }
899 case 1 : /* mv_left_right */
900 {
901 B_MODE_INFO *bmi = &mi->bmi[0];
902 MV *mv = &bmi->mv.as_mv;
903
904 x1 = x0 + 4 + (mv->col >> 3);
905 y1 = y0 + 8 + (mv->row >> 3);
906
907 constrain_line (x0+4, &x1, y0+8, &y1, width, height);
908 vp8_blit_line (x0+4, x1, y0+8, y1, y_buffer, y_stride);
909
910 bmi = &mi->bmi[2];
911
912 x1 = x0 +12 + (mv->col >> 3);
913 y1 = y0 + 8 + (mv->row >> 3);
914
915 constrain_line (x0+12, &x1, y0+8, &y1, width, height);
916 vp8_blit_line (x0+12, x1, y0+8, y1, y_buffer, y_stride);
917
918 break;
919 }
920 case 2 : /* mv_quarters */
921 {
922 B_MODE_INFO *bmi = &mi->bmi[0];
923 MV *mv = &bmi->mv.as_mv;
924
925 x1 = x0 + 4 + (mv->col >> 3);
926 y1 = y0 + 4 + (mv->row >> 3);
927
928 constrain_line (x0+4, &x1, y0+4, &y1, width, height);
929 vp8_blit_line (x0+4, x1, y0+4, y1, y_buffer, y_stride);
930
931 bmi = &mi->bmi[2];
932
933 x1 = x0 +12 + (mv->col >> 3);
934 y1 = y0 + 4 + (mv->row >> 3);
935
936 constrain_line (x0+12, &x1, y0+4, &y1, width, height);
937 vp8_blit_line (x0+12, x1, y0+4, y1, y_buffer, y_stride);
938
939 bmi = &mi->bmi[8];
940
941 x1 = x0 + 4 + (mv->col >> 3);
942 y1 = y0 +12 + (mv->row >> 3);
943
944 constrain_line (x0+4, &x1, y0+12, &y1, width, height);
945 vp8_blit_line (x0+4, x1, y0+12, y1, y_buffer, y_stride);
946
947 bmi = &mi->bmi[10];
948
949 x1 = x0 +12 + (mv->col >> 3);
950 y1 = y0 +12 + (mv->row >> 3);
951
952 constrain_line (x0+12, &x1, y0+12, &y1, width, height);
953 vp8_blit_line (x0+12, x1, y0+12, y1, y_buffer, y_stride);
954 break;
955 }
956 default :
957 {
958 B_MODE_INFO *bmi = mi->bmi;
959 int bx0, by0;
960
961 for (by0 = y0; by0 < (y0+16); by0 += 4)
962 {
963 for (bx0 = x0; bx0 < (x0+16); bx0 += 4)
964 {
965 MV *mv = &bmi->mv.as_mv;
966
967 x1 = bx0 + 2 + (mv->col >> 3);
968 y1 = by0 + 2 + (mv->row >> 3);
969
970 constrain_line (bx0+2, &x1, by0+2, &y1, width, height);
971 vp8_blit_line (bx0+2, x1, by0+2, y1, y_buffer, y_stride);
972
973 bmi++;
974 }
975 }
976 }
977 }
978 }
979 else if (mi->mbmi.mode >= NEARESTMV)
980 {
981 MV *mv = &mi->mbmi.mv.as_mv;
982 const int lx0 = x0 + 8;
983 const int ly0 = y0 + 8;
984
985 x1 = lx0 + (mv->col >> 3);
986 y1 = ly0 + (mv->row >> 3);
987
988 if (x1 != lx0 && y1 != ly0)
989 {
990 constrain_line (lx0, &x1, ly0-1, &y1, width, height);
991 vp8_blit_line (lx0, x1, ly0-1, y1, y_buffer, y_stride);
992
993 constrain_line (lx0, &x1, ly0+1, &y1, width, height);
994 vp8_blit_line (lx0, x1, ly0+1, y1, y_buffer, y_stride);
995 }
996 else
997 vp8_blit_line (lx0, x1, ly0, y1, y_buffer, y_stride);
998 }
999 mi++;
1000 }
1001 mi++;
1002 }
1003 }
1004
1005 /* Color in block modes */
1006 if (flags & VP8D_DEBUG_CLR_BLK_MODES)
1007 {
1008 int y, x;
1009 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
1010 int width = post->y_width;
1011 int height = post->y_height;
1012 unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
1013 unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
1014 unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
1015 int y_stride = oci->post_proc_buffer.y_stride;
1016 MODE_INFO *mi = oci->mi;
1017
1018 for (y = 0; y < height; y += 16)
1019 {
1020 for (x = 0; x < width; x += 16)
1021 {
1022 int Y = 0, U = 0, V = 0;
1023
1024 if (mi->mbmi.mode == B_PRED)
1025 {
1026 int by, bx;
1027 unsigned char *yl, *ul, *vl;
1028 B_MODE_INFO *bmi = mi->bmi;
1029
1030 yl = y_ptr + x;
1031 ul = u_ptr + (x>>1);
1032 vl = v_ptr + (x>>1);
1033
1034 for (by = 0; by < 16; by += 4)
1035 {
1036 for (bx = 0; bx < 16; bx += 4)
1037 {
1038 Y = B_PREDICTION_MODE_colors[bmi->mode][0];
1039 U = B_PREDICTION_MODE_colors[bmi->mode][1];
1040 V = B_PREDICTION_MODE_colors[bmi->mode][2];
1041
1042 POSTPROC_INVOKE(RTCD_VTABLE(oci), blend_b)
1043 (yl+bx, ul+(bx>>1), vl+(bx>>1), Y, U, V, 0xc000, y_stride);
1044
1045 bmi++;
1046 }
1047
1048 yl += y_stride*4;
1049 ul += y_stride*1;
1050 vl += y_stride*1;
1051 }
1052 }
1053 else
1054 {
1055 Y = MB_PREDICTION_MODE_colors[mi->mbmi.mode][0];
1056 U = MB_PREDICTION_MODE_colors[mi->mbmi.mode][1];
1057 V = MB_PREDICTION_MODE_colors[mi->mbmi.mode][2];
1058
1059 POSTPROC_INVOKE(RTCD_VTABLE(oci), blend_mb_inner)
1060 (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1061 }
1062 mi++;
1063 }
1064 y_ptr += y_stride*16;
1065 u_ptr += y_stride*4;
1066 v_ptr += y_stride*4;
1067
1068 mi++;
1069 }
1070 }
1071
1072 /* Color in frame reference blocks */
1073 if (flags & VP8D_DEBUG_CLR_FRM_REF_BLKS)
1074 {
1075 int y, x;
1076 YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
1077 int width = post->y_width;
1078 int height = post->y_height;
1079 unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
1080 unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
1081 unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
1082 int y_stride = oci->post_proc_buffer.y_stride;
1083 MODE_INFO *mi = oci->mi;
1084
1085 for (y = 0; y < height; y += 16)
1086 {
1087 for (x = 0; x < width; x +=16)
1088 {
1089 int Y = 0, U = 0, V = 0;
1090
1091 Y = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][0];
1092 U = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][1];
1093 V = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][2];
1094
1095 POSTPROC_INVOKE(RTCD_VTABLE(oci), blend_mb_outer)
1096 (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
1097
1098 mi++;
1099 }
1100 y_ptr += y_stride*16;
1101 u_ptr += y_stride*4;
1102 v_ptr += y_stride*4;
1103
1104 mi++;
1105 }
1106 }
1107
1108 *dest = oci->post_proc_buffer;
1109
1110 /* handle problem with extending borders */
1111 dest->y_width = oci->Width;
1112 dest->y_height = oci->Height;
1113 dest->uv_height = dest->y_height / 2;
1114 return 0;
1115 }
1116