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#include <math.h>
12#include <stdlib.h>
13#include <stdio.h>
14
15#include "./vpx_config.h"
16#include "./vpx_scale_rtcd.h"
17#include "./vp9_rtcd.h"
18
19#include "vpx_scale/vpx_scale.h"
20#include "vpx_scale/yv12config.h"
21
22#include "vp9/common/vp9_onyxc_int.h"
23#include "vp9/common/vp9_postproc.h"
24#include "vp9/common/vp9_systemdependent.h"
25#include "vp9/common/vp9_textblit.h"
26
27#define RGB_TO_YUV(t)                                            \
28  ( (0.257*(float)(t >> 16))  + (0.504*(float)(t >> 8 & 0xff)) + \
29    (0.098*(float)(t & 0xff)) + 16),                             \
30  (-(0.148*(float)(t >> 16))  - (0.291*(float)(t >> 8 & 0xff)) + \
31    (0.439*(float)(t & 0xff)) + 128),                            \
32  ( (0.439*(float)(t >> 16))  - (0.368*(float)(t >> 8 & 0xff)) - \
33    (0.071*(float)(t & 0xff)) + 128)
34
35/* global constants */
36#if 0 && CONFIG_POSTPROC_VISUALIZER
37static const unsigned char MB_PREDICTION_MODE_colors[MB_MODE_COUNT][3] = {
38  { RGB_TO_YUV(0x98FB98) },   /* PaleGreen */
39  { RGB_TO_YUV(0x00FF00) },   /* Green */
40  { RGB_TO_YUV(0xADFF2F) },   /* GreenYellow */
41  { RGB_TO_YUV(0x8F0000) },   /* Dark Red */
42  { RGB_TO_YUV(0x008F8F) },   /* Dark Cyan */
43  { RGB_TO_YUV(0x008F8F) },   /* Dark Cyan */
44  { RGB_TO_YUV(0x008F8F) },   /* Dark Cyan */
45  { RGB_TO_YUV(0x8F0000) },   /* Dark Red */
46  { RGB_TO_YUV(0x8F0000) },   /* Dark Red */
47  { RGB_TO_YUV(0x228B22) },   /* ForestGreen */
48  { RGB_TO_YUV(0x006400) },   /* DarkGreen */
49  { RGB_TO_YUV(0x98F5FF) },   /* Cadet Blue */
50  { RGB_TO_YUV(0x6CA6CD) },   /* Sky Blue */
51  { RGB_TO_YUV(0x00008B) },   /* Dark blue */
52  { RGB_TO_YUV(0x551A8B) },   /* Purple */
53  { RGB_TO_YUV(0xFF0000) }    /* Red */
54  { RGB_TO_YUV(0xCC33FF) },   /* Magenta */
55};
56
57static const unsigned char B_PREDICTION_MODE_colors[INTRA_MODES][3] = {
58  { RGB_TO_YUV(0x6633ff) },   /* Purple */
59  { RGB_TO_YUV(0xcc33ff) },   /* Magenta */
60  { RGB_TO_YUV(0xff33cc) },   /* Pink */
61  { RGB_TO_YUV(0xff3366) },   /* Coral */
62  { RGB_TO_YUV(0x3366ff) },   /* Blue */
63  { RGB_TO_YUV(0xed00f5) },   /* Dark Blue */
64  { RGB_TO_YUV(0x2e00b8) },   /* Dark Purple */
65  { RGB_TO_YUV(0xff6633) },   /* Orange */
66  { RGB_TO_YUV(0x33ccff) },   /* Light Blue */
67  { RGB_TO_YUV(0x8ab800) },   /* Green */
68  { RGB_TO_YUV(0xffcc33) },   /* Light Orange */
69  { RGB_TO_YUV(0x33ffcc) },   /* Aqua */
70  { RGB_TO_YUV(0x66ff33) },   /* Light Green */
71  { RGB_TO_YUV(0xccff33) },   /* Yellow */
72};
73
74static const unsigned char MV_REFERENCE_FRAME_colors[MAX_REF_FRAMES][3] = {
75  { RGB_TO_YUV(0x00ff00) },   /* Blue */
76  { RGB_TO_YUV(0x0000ff) },   /* Green */
77  { RGB_TO_YUV(0xffff00) },   /* Yellow */
78  { RGB_TO_YUV(0xff0000) },   /* Red */
79};
80#endif
81
82static const short kernel5[] = {
83  1, 1, 4, 1, 1
84};
85
86const short vp9_rv[] = {
87  8, 5, 2, 2, 8, 12, 4, 9, 8, 3,
88  0, 3, 9, 0, 0, 0, 8, 3, 14, 4,
89  10, 1, 11, 14, 1, 14, 9, 6, 12, 11,
90  8, 6, 10, 0, 0, 8, 9, 0, 3, 14,
91  8, 11, 13, 4, 2, 9, 0, 3, 9, 6,
92  1, 2, 3, 14, 13, 1, 8, 2, 9, 7,
93  3, 3, 1, 13, 13, 6, 6, 5, 2, 7,
94  11, 9, 11, 8, 7, 3, 2, 0, 13, 13,
95  14, 4, 12, 5, 12, 10, 8, 10, 13, 10,
96  4, 14, 4, 10, 0, 8, 11, 1, 13, 7,
97  7, 14, 6, 14, 13, 2, 13, 5, 4, 4,
98  0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
99  8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
100  3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
101  3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
102  13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
103  5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
104  9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
105  4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
106  3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
107  11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
108  5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
109  0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
110  10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
111  4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
112  0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
113  8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
114  3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
115  3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
116  13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
117  5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
118  9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
119  4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
120  3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
121  11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
122  5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
123  0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
124  10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
125  4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
126  3, 8, 3, 7, 8, 5, 11, 4, 12, 3,
127  11, 9, 14, 8, 14, 13, 4, 3, 1, 2,
128  14, 6, 5, 4, 4, 11, 4, 6, 2, 1,
129  5, 8, 8, 12, 13, 5, 14, 10, 12, 13,
130  0, 9, 5, 5, 11, 10, 13, 9, 10, 13,
131};
132
133void vp9_post_proc_down_and_across_c(const uint8_t *src_ptr,
134                                     uint8_t *dst_ptr,
135                                     int src_pixels_per_line,
136                                     int dst_pixels_per_line,
137                                     int rows,
138                                     int cols,
139                                     int flimit) {
140  uint8_t const *p_src;
141  uint8_t *p_dst;
142  int row;
143  int col;
144  int i;
145  int v;
146  int pitch = src_pixels_per_line;
147  uint8_t d[8];
148  (void)dst_pixels_per_line;
149
150  for (row = 0; row < rows; row++) {
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      int kernel = 4;
157      int v = p_src[col];
158
159      for (i = -2; i <= 2; i++) {
160        if (abs(v - p_src[col + i * pitch]) > flimit)
161          goto down_skip_convolve;
162
163        kernel += kernel5[2 + i] * p_src[col + i * pitch];
164      }
165
166      v = (kernel >> 3);
167    down_skip_convolve:
168      p_dst[col] = v;
169    }
170
171    /* now post_proc_across */
172    p_src = dst_ptr;
173    p_dst = dst_ptr;
174
175    for (i = 0; i < 8; i++)
176      d[i] = p_src[i];
177
178    for (col = 0; col < cols; col++) {
179      int kernel = 4;
180      v = p_src[col];
181
182      d[col & 7] = v;
183
184      for (i = -2; i <= 2; i++) {
185        if (abs(v - p_src[col + i]) > flimit)
186          goto across_skip_convolve;
187
188        kernel += kernel5[2 + i] * p_src[col + i];
189      }
190
191      d[col & 7] = (kernel >> 3);
192    across_skip_convolve:
193
194      if (col >= 2)
195        p_dst[col - 2] = d[(col - 2) & 7];
196    }
197
198    /* handle the last two pixels */
199    p_dst[col - 2] = d[(col - 2) & 7];
200    p_dst[col - 1] = d[(col - 1) & 7];
201
202
203    /* next row */
204    src_ptr += pitch;
205    dst_ptr += pitch;
206  }
207}
208
209static int q2mbl(int x) {
210  if (x < 20) x = 20;
211
212  x = 50 + (x - 50) * 10 / 8;
213  return x * x / 3;
214}
215
216void vp9_mbpost_proc_across_ip_c(uint8_t *src, int pitch,
217                                 int rows, int cols, int flimit) {
218  int r, c, i;
219
220  uint8_t *s = src;
221  uint8_t d[16];
222
223
224  for (r = 0; r < rows; r++) {
225    int sumsq = 0;
226    int sum   = 0;
227
228    for (i = -8; i <= 6; i++) {
229      sumsq += s[i] * s[i];
230      sum   += s[i];
231      d[i + 8] = 0;
232    }
233
234    for (c = 0; c < cols + 8; c++) {
235      int x = s[c + 7] - s[c - 8];
236      int y = s[c + 7] + s[c - 8];
237
238      sum  += x;
239      sumsq += x * y;
240
241      d[c & 15] = s[c];
242
243      if (sumsq * 15 - sum * sum < flimit) {
244        d[c & 15] = (8 + sum + s[c]) >> 4;
245      }
246
247      s[c - 8] = d[(c - 8) & 15];
248    }
249
250    s += pitch;
251  }
252}
253
254void vp9_mbpost_proc_down_c(uint8_t *dst, int pitch,
255                            int rows, int cols, int flimit) {
256  int r, c, i;
257  const short *rv3 = &vp9_rv[63 & rand()]; // NOLINT
258
259  for (c = 0; c < cols; c++) {
260    uint8_t *s = &dst[c];
261    int sumsq = 0;
262    int sum   = 0;
263    uint8_t d[16];
264    const short *rv2 = rv3 + ((c * 17) & 127);
265
266    for (i = -8; i <= 6; i++) {
267      sumsq += s[i * pitch] * s[i * pitch];
268      sum   += s[i * pitch];
269    }
270
271    for (r = 0; r < rows + 8; r++) {
272      sumsq += s[7 * pitch] * s[ 7 * pitch] - s[-8 * pitch] * s[-8 * pitch];
273      sum  += s[7 * pitch] - s[-8 * pitch];
274      d[r & 15] = s[0];
275
276      if (sumsq * 15 - sum * sum < flimit) {
277        d[r & 15] = (rv2[r & 127] + sum + s[0]) >> 4;
278      }
279
280      s[-8 * pitch] = d[(r - 8) & 15];
281      s += pitch;
282    }
283  }
284}
285
286static void deblock_and_de_macro_block(YV12_BUFFER_CONFIG   *source,
287                                       YV12_BUFFER_CONFIG   *post,
288                                       int                   q,
289                                       int                   low_var_thresh,
290                                       int                   flag) {
291  double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
292  int ppl = (int)(level + .5);
293  (void) low_var_thresh;
294  (void) flag;
295
296  vp9_post_proc_down_and_across(source->y_buffer, post->y_buffer,
297                                source->y_stride, post->y_stride,
298                                source->y_height, source->y_width, ppl);
299
300  vp9_mbpost_proc_across_ip(post->y_buffer, post->y_stride, post->y_height,
301                            post->y_width, q2mbl(q));
302
303  vp9_mbpost_proc_down(post->y_buffer, post->y_stride, post->y_height,
304                       post->y_width, q2mbl(q));
305
306  vp9_post_proc_down_and_across(source->u_buffer, post->u_buffer,
307                                source->uv_stride, post->uv_stride,
308                                source->uv_height, source->uv_width, ppl);
309  vp9_post_proc_down_and_across(source->v_buffer, post->v_buffer,
310                                source->uv_stride, post->uv_stride,
311                                source->uv_height, source->uv_width, ppl);
312}
313
314void vp9_deblock(const YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst,
315                 int q) {
316  const int ppl = (int)(6.0e-05 * q * q * q - 0.0067 * q * q + 0.306 * q
317                        + 0.0065 + 0.5);
318  int i;
319
320  const uint8_t *const srcs[4] = {src->y_buffer, src->u_buffer, src->v_buffer,
321                                  src->alpha_buffer};
322  const int src_strides[4] = {src->y_stride, src->uv_stride, src->uv_stride,
323                              src->alpha_stride};
324  const int src_widths[4] = {src->y_width, src->uv_width, src->uv_width,
325                             src->alpha_width};
326  const int src_heights[4] = {src->y_height, src->uv_height, src->uv_height,
327                              src->alpha_height};
328
329  uint8_t *const dsts[4] = {dst->y_buffer, dst->u_buffer, dst->v_buffer,
330                            dst->alpha_buffer};
331  const int dst_strides[4] = {dst->y_stride, dst->uv_stride, dst->uv_stride,
332                              dst->alpha_stride};
333
334  for (i = 0; i < MAX_MB_PLANE; ++i)
335    vp9_post_proc_down_and_across(srcs[i], dsts[i],
336                                  src_strides[i], dst_strides[i],
337                                  src_heights[i], src_widths[i], ppl);
338}
339
340void vp9_denoise(const YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst,
341                 int q) {
342  const int ppl = (int)(6.0e-05 * q * q * q - 0.0067 * q * q + 0.306 * q
343                        + 0.0065 + 0.5);
344  int i;
345
346  const uint8_t *const srcs[4] = {src->y_buffer, src->u_buffer, src->v_buffer,
347                                  src->alpha_buffer};
348  const int src_strides[4] = {src->y_stride, src->uv_stride, src->uv_stride,
349                              src->alpha_stride};
350  const int src_widths[4] = {src->y_width, src->uv_width, src->uv_width,
351                             src->alpha_width};
352  const int src_heights[4] = {src->y_height, src->uv_height, src->uv_height,
353                              src->alpha_height};
354
355  uint8_t *const dsts[4] = {dst->y_buffer, dst->u_buffer, dst->v_buffer,
356                            dst->alpha_buffer};
357  const int dst_strides[4] = {dst->y_stride, dst->uv_stride, dst->uv_stride,
358                              dst->alpha_stride};
359
360  for (i = 0; i < MAX_MB_PLANE; ++i) {
361    const int src_stride = src_strides[i];
362    const uint8_t *const src = srcs[i] + 2 * src_stride + 2;
363    const int src_width = src_widths[i] - 4;
364    const int src_height = src_heights[i] - 4;
365
366    const int dst_stride = dst_strides[i];
367    uint8_t *const dst = dsts[i] + 2 * dst_stride + 2;
368
369    vp9_post_proc_down_and_across(src, dst, src_stride, dst_stride,
370                                  src_height, src_width, ppl);
371  }
372}
373
374static double gaussian(double sigma, double mu, double x) {
375  return 1 / (sigma * sqrt(2.0 * 3.14159265)) *
376         (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma)));
377}
378
379static void fillrd(struct postproc_state *state, int q, int a) {
380  char char_dist[300];
381
382  double sigma;
383  int ai = a, qi = q, i;
384
385  vp9_clear_system_state();
386
387  sigma = ai + .5 + .6 * (63 - qi) / 63.0;
388
389  /* set up a lookup table of 256 entries that matches
390   * a gaussian distribution with sigma determined by q.
391   */
392  {
393    double i;
394    int next, j;
395
396    next = 0;
397
398    for (i = -32; i < 32; i++) {
399      int a = (int)(0.5 + 256 * gaussian(sigma, 0, i));
400
401      if (a) {
402        for (j = 0; j < a; j++) {
403          char_dist[next + j] = (char) i;
404        }
405
406        next = next + j;
407      }
408    }
409
410    for (; next < 256; next++)
411      char_dist[next] = 0;
412  }
413
414  for (i = 0; i < 3072; i++) {
415    state->noise[i] = char_dist[rand() & 0xff];  // NOLINT
416  }
417
418  for (i = 0; i < 16; i++) {
419    state->blackclamp[i] = -char_dist[0];
420    state->whiteclamp[i] = -char_dist[0];
421    state->bothclamp[i] = -2 * char_dist[0];
422  }
423
424  state->last_q = q;
425  state->last_noise = a;
426}
427
428void vp9_plane_add_noise_c(uint8_t *start, char *noise,
429                           char blackclamp[16],
430                           char whiteclamp[16],
431                           char bothclamp[16],
432                           unsigned int width, unsigned int height, int pitch) {
433  unsigned int i, j;
434
435  for (i = 0; i < height; i++) {
436    uint8_t *pos = start + i * pitch;
437    char  *ref = (char *)(noise + (rand() & 0xff));  // NOLINT
438
439    for (j = 0; j < width; j++) {
440      if (pos[j] < blackclamp[0])
441        pos[j] = blackclamp[0];
442
443      if (pos[j] > 255 + whiteclamp[0])
444        pos[j] = 255 + whiteclamp[0];
445
446      pos[j] += ref[j];
447    }
448  }
449}
450
451/* Blend the macro block with a solid colored square.  Leave the
452 * edges unblended to give distinction to macro blocks in areas
453 * filled with the same color block.
454 */
455void vp9_blend_mb_inner_c(uint8_t *y, uint8_t *u, uint8_t *v,
456                          int y1, int u1, int v1, int alpha, int stride) {
457  int i, j;
458  int y1_const = y1 * ((1 << 16) - alpha);
459  int u1_const = u1 * ((1 << 16) - alpha);
460  int v1_const = v1 * ((1 << 16) - alpha);
461
462  y += 2 * stride + 2;
463  for (i = 0; i < 12; i++) {
464    for (j = 0; j < 12; j++) {
465      y[j] = (y[j] * alpha + y1_const) >> 16;
466    }
467    y += stride;
468  }
469
470  stride >>= 1;
471
472  u += stride + 1;
473  v += stride + 1;
474
475  for (i = 0; i < 6; i++) {
476    for (j = 0; j < 6; j++) {
477      u[j] = (u[j] * alpha + u1_const) >> 16;
478      v[j] = (v[j] * alpha + v1_const) >> 16;
479    }
480    u += stride;
481    v += stride;
482  }
483}
484
485/* Blend only the edge of the macro block.  Leave center
486 * unblended to allow for other visualizations to be layered.
487 */
488void vp9_blend_mb_outer_c(uint8_t *y, uint8_t *u, uint8_t *v,
489                          int y1, int u1, int v1, int alpha, int stride) {
490  int i, j;
491  int y1_const = y1 * ((1 << 16) - alpha);
492  int u1_const = u1 * ((1 << 16) - alpha);
493  int v1_const = v1 * ((1 << 16) - alpha);
494
495  for (i = 0; i < 2; i++) {
496    for (j = 0; j < 16; j++) {
497      y[j] = (y[j] * alpha + y1_const) >> 16;
498    }
499    y += stride;
500  }
501
502  for (i = 0; i < 12; i++) {
503    y[0]  = (y[0] * alpha  + y1_const) >> 16;
504    y[1]  = (y[1] * alpha  + y1_const) >> 16;
505    y[14] = (y[14] * alpha + y1_const) >> 16;
506    y[15] = (y[15] * alpha + y1_const) >> 16;
507    y += stride;
508  }
509
510  for (i = 0; i < 2; i++) {
511    for (j = 0; j < 16; j++) {
512      y[j] = (y[j] * alpha + y1_const) >> 16;
513    }
514    y += stride;
515  }
516
517  stride >>= 1;
518
519  for (j = 0; j < 8; j++) {
520    u[j] = (u[j] * alpha + u1_const) >> 16;
521    v[j] = (v[j] * alpha + v1_const) >> 16;
522  }
523  u += stride;
524  v += stride;
525
526  for (i = 0; i < 6; i++) {
527    u[0] = (u[0] * alpha + u1_const) >> 16;
528    v[0] = (v[0] * alpha + v1_const) >> 16;
529
530    u[7] = (u[7] * alpha + u1_const) >> 16;
531    v[7] = (v[7] * alpha + v1_const) >> 16;
532
533    u += stride;
534    v += stride;
535  }
536
537  for (j = 0; j < 8; j++) {
538    u[j] = (u[j] * alpha + u1_const) >> 16;
539    v[j] = (v[j] * alpha + v1_const) >> 16;
540  }
541}
542
543void vp9_blend_b_c(uint8_t *y, uint8_t *u, uint8_t *v,
544                   int y1, int u1, int v1, int alpha, int stride) {
545  int i, j;
546  int y1_const = y1 * ((1 << 16) - alpha);
547  int u1_const = u1 * ((1 << 16) - alpha);
548  int v1_const = v1 * ((1 << 16) - alpha);
549
550  for (i = 0; i < 4; i++) {
551    for (j = 0; j < 4; j++) {
552      y[j] = (y[j] * alpha + y1_const) >> 16;
553    }
554    y += stride;
555  }
556
557  stride >>= 1;
558
559  for (i = 0; i < 2; i++) {
560    for (j = 0; j < 2; j++) {
561      u[j] = (u[j] * alpha + u1_const) >> 16;
562      v[j] = (v[j] * alpha + v1_const) >> 16;
563    }
564    u += stride;
565    v += stride;
566  }
567}
568
569static void constrain_line(int x0, int *x1, int y0, int *y1,
570                           int width, int height) {
571  int dx;
572  int dy;
573
574  if (*x1 > width) {
575    dx = *x1 - x0;
576    dy = *y1 - y0;
577
578    *x1 = width;
579    if (dx)
580      *y1 = ((width - x0) * dy) / dx + y0;
581  }
582  if (*x1 < 0) {
583    dx = *x1 - x0;
584    dy = *y1 - y0;
585
586    *x1 = 0;
587    if (dx)
588      *y1 = ((0 - x0) * dy) / dx + y0;
589  }
590  if (*y1 > height) {
591    dx = *x1 - x0;
592    dy = *y1 - y0;
593
594    *y1 = height;
595    if (dy)
596      *x1 = ((height - y0) * dx) / dy + x0;
597  }
598  if (*y1 < 0) {
599    dx = *x1 - x0;
600    dy = *y1 - y0;
601
602    *y1 = 0;
603    if (dy)
604      *x1 = ((0 - y0) * dx) / dy + x0;
605  }
606}
607
608int vp9_post_proc_frame(struct VP9Common *cm,
609                        YV12_BUFFER_CONFIG *dest, vp9_ppflags_t *ppflags) {
610  const int q = MIN(63, cm->lf.filter_level * 10 / 6);
611  const int flags = ppflags->post_proc_flag;
612  YV12_BUFFER_CONFIG *const ppbuf = &cm->post_proc_buffer;
613  struct postproc_state *const ppstate = &cm->postproc_state;
614
615  if (!cm->frame_to_show)
616    return -1;
617
618  if (!flags) {
619    *dest = *cm->frame_to_show;
620    return 0;
621  }
622
623  vp9_clear_system_state();
624
625  if (flags & VP9D_DEMACROBLOCK) {
626    deblock_and_de_macro_block(cm->frame_to_show, ppbuf,
627                               q + (ppflags->deblocking_level - 5) * 10, 1, 0);
628  } else if (flags & VP9D_DEBLOCK) {
629    vp9_deblock(cm->frame_to_show, ppbuf, q);
630  } else {
631    vp8_yv12_copy_frame(cm->frame_to_show, ppbuf);
632  }
633
634  if (flags & VP9D_ADDNOISE) {
635    const int noise_level = ppflags->noise_level;
636    if (ppstate->last_q != q ||
637        ppstate->last_noise != noise_level) {
638      fillrd(ppstate, 63 - q, noise_level);
639    }
640
641    vp9_plane_add_noise(ppbuf->y_buffer, ppstate->noise, ppstate->blackclamp,
642                        ppstate->whiteclamp, ppstate->bothclamp,
643                        ppbuf->y_width, ppbuf->y_height, ppbuf->y_stride);
644  }
645
646#if 0 && CONFIG_POSTPROC_VISUALIZER
647  if (flags & VP9D_DEBUG_TXT_FRAME_INFO) {
648    char message[512];
649    snprintf(message, sizeof(message) -1,
650             "F%1dG%1dQ%3dF%3dP%d_s%dx%d",
651             (cm->frame_type == KEY_FRAME),
652             cm->refresh_golden_frame,
653             cm->base_qindex,
654             cm->filter_level,
655             flags,
656             cm->mb_cols, cm->mb_rows);
657    vp9_blit_text(message, ppbuf->y_buffer, ppbuf->y_stride);
658  }
659
660  if (flags & VP9D_DEBUG_TXT_MBLK_MODES) {
661    int i, j;
662    uint8_t *y_ptr;
663    int mb_rows = ppbuf->y_height >> 4;
664    int mb_cols = ppbuf->y_width  >> 4;
665    int mb_index = 0;
666    MODE_INFO *mi = cm->mi;
667
668    y_ptr = post->y_buffer + 4 * post->y_stride + 4;
669
670    /* vp9_filter each macro block */
671    for (i = 0; i < mb_rows; i++) {
672      for (j = 0; j < mb_cols; j++) {
673        char zz[4];
674
675        snprintf(zz, sizeof(zz) - 1, "%c", mi[mb_index].mbmi.mode + 'a');
676
677        vp9_blit_text(zz, y_ptr, post->y_stride);
678        mb_index++;
679        y_ptr += 16;
680      }
681
682      mb_index++; /* border */
683      y_ptr += post->y_stride  * 16 - post->y_width;
684    }
685  }
686
687  if (flags & VP9D_DEBUG_TXT_DC_DIFF) {
688    int i, j;
689    uint8_t *y_ptr;
690    int mb_rows = ppbuf->y_height >> 4;
691    int mb_cols = ppbuf->y_width  >> 4;
692    int mb_index = 0;
693    MODE_INFO *mi = cm->mi;
694
695    y_ptr = post->y_buffer + 4 * post->y_stride + 4;
696
697    /* vp9_filter each macro block */
698    for (i = 0; i < mb_rows; i++) {
699      for (j = 0; j < mb_cols; j++) {
700        char zz[4];
701        int dc_diff = !(mi[mb_index].mbmi.mode != I4X4_PRED &&
702                        mi[mb_index].mbmi.mode != SPLITMV &&
703                        mi[mb_index].mbmi.skip);
704
705        if (cm->frame_type == KEY_FRAME)
706          snprintf(zz, sizeof(zz) - 1, "a");
707        else
708          snprintf(zz, sizeof(zz) - 1, "%c", dc_diff + '0');
709
710        vp9_blit_text(zz, y_ptr, post->y_stride);
711        mb_index++;
712        y_ptr += 16;
713      }
714
715      mb_index++; /* border */
716      y_ptr += post->y_stride  * 16 - post->y_width;
717    }
718  }
719
720  if (flags & VP9D_DEBUG_TXT_RATE_INFO) {
721    char message[512];
722    snprintf(message, sizeof(message),
723             "Bitrate: %10.2f framerate: %10.2f ",
724             cm->bitrate, cm->framerate);
725    vp9_blit_text(message, ppbuf->y_buffer, ppbuf->y_stride);
726  }
727
728  /* Draw motion vectors */
729  if ((flags & VP9D_DEBUG_DRAW_MV) && ppflags->display_mv_flag) {
730    int width  = ppbuf->y_width;
731    int height = ppbuf->y_height;
732    uint8_t *y_buffer = ppbuf->y_buffer;
733    int y_stride = ppbuf->y_stride;
734    MODE_INFO *mi = cm->mi;
735    int x0, y0;
736
737    for (y0 = 0; y0 < height; y0 += 16) {
738      for (x0 = 0; x0 < width; x0 += 16) {
739        int x1, y1;
740
741        if (!(ppflags->display_mv_flag & (1 << mi->mbmi.mode))) {
742          mi++;
743          continue;
744        }
745
746        if (mi->mbmi.mode == SPLITMV) {
747          switch (mi->mbmi.partitioning) {
748            case PARTITIONING_16X8 : {  /* mv_top_bottom */
749              union b_mode_info *bmi = &mi->bmi[0];
750              MV *mv = &bmi->mv.as_mv;
751
752              x1 = x0 + 8 + (mv->col >> 3);
753              y1 = y0 + 4 + (mv->row >> 3);
754
755              constrain_line(x0 + 8, &x1, y0 + 4, &y1, width, height);
756              vp9_blit_line(x0 + 8,  x1, y0 + 4,  y1, y_buffer, y_stride);
757
758              bmi = &mi->bmi[8];
759
760              x1 = x0 + 8 + (mv->col >> 3);
761              y1 = y0 + 12 + (mv->row >> 3);
762
763              constrain_line(x0 + 8, &x1, y0 + 12, &y1, width, height);
764              vp9_blit_line(x0 + 8,  x1, y0 + 12,  y1, y_buffer, y_stride);
765
766              break;
767            }
768            case PARTITIONING_8X16 : {  /* mv_left_right */
769              union b_mode_info *bmi = &mi->bmi[0];
770              MV *mv = &bmi->mv.as_mv;
771
772              x1 = x0 + 4 + (mv->col >> 3);
773              y1 = y0 + 8 + (mv->row >> 3);
774
775              constrain_line(x0 + 4, &x1, y0 + 8, &y1, width, height);
776              vp9_blit_line(x0 + 4,  x1, y0 + 8,  y1, y_buffer, y_stride);
777
778              bmi = &mi->bmi[2];
779
780              x1 = x0 + 12 + (mv->col >> 3);
781              y1 = y0 + 8 + (mv->row >> 3);
782
783              constrain_line(x0 + 12, &x1, y0 + 8, &y1, width, height);
784              vp9_blit_line(x0 + 12,  x1, y0 + 8,  y1, y_buffer, y_stride);
785
786              break;
787            }
788            case PARTITIONING_8X8 : {  /* mv_quarters   */
789              union b_mode_info *bmi = &mi->bmi[0];
790              MV *mv = &bmi->mv.as_mv;
791
792              x1 = x0 + 4 + (mv->col >> 3);
793              y1 = y0 + 4 + (mv->row >> 3);
794
795              constrain_line(x0 + 4, &x1, y0 + 4, &y1, width, height);
796              vp9_blit_line(x0 + 4,  x1, y0 + 4,  y1, y_buffer, y_stride);
797
798              bmi = &mi->bmi[2];
799
800              x1 = x0 + 12 + (mv->col >> 3);
801              y1 = y0 + 4 + (mv->row >> 3);
802
803              constrain_line(x0 + 12, &x1, y0 + 4, &y1, width, height);
804              vp9_blit_line(x0 + 12,  x1, y0 + 4,  y1, y_buffer, y_stride);
805
806              bmi = &mi->bmi[8];
807
808              x1 = x0 + 4 + (mv->col >> 3);
809              y1 = y0 + 12 + (mv->row >> 3);
810
811              constrain_line(x0 + 4, &x1, y0 + 12, &y1, width, height);
812              vp9_blit_line(x0 + 4,  x1, y0 + 12,  y1, y_buffer, y_stride);
813
814              bmi = &mi->bmi[10];
815
816              x1 = x0 + 12 + (mv->col >> 3);
817              y1 = y0 + 12 + (mv->row >> 3);
818
819              constrain_line(x0 + 12, &x1, y0 + 12, &y1, width, height);
820              vp9_blit_line(x0 + 12,  x1, y0 + 12,  y1, y_buffer, y_stride);
821              break;
822            }
823            case PARTITIONING_4X4:
824            default : {
825              union b_mode_info *bmi = mi->bmi;
826              int bx0, by0;
827
828              for (by0 = y0; by0 < (y0 + 16); by0 += 4) {
829                for (bx0 = x0; bx0 < (x0 + 16); bx0 += 4) {
830                  MV *mv = &bmi->mv.as_mv;
831
832                  x1 = bx0 + 2 + (mv->col >> 3);
833                  y1 = by0 + 2 + (mv->row >> 3);
834
835                  constrain_line(bx0 + 2, &x1, by0 + 2, &y1, width, height);
836                  vp9_blit_line(bx0 + 2,  x1, by0 + 2,  y1, y_buffer, y_stride);
837
838                  bmi++;
839                }
840              }
841            }
842          }
843        } else if (is_inter_mode(mi->mbmi.mode)) {
844          MV *mv = &mi->mbmi.mv.as_mv;
845          const int lx0 = x0 + 8;
846          const int ly0 = y0 + 8;
847
848          x1 = lx0 + (mv->col >> 3);
849          y1 = ly0 + (mv->row >> 3);
850
851          if (x1 != lx0 && y1 != ly0) {
852            constrain_line(lx0, &x1, ly0 - 1, &y1, width, height);
853            vp9_blit_line(lx0,  x1, ly0 - 1,  y1, y_buffer, y_stride);
854
855            constrain_line(lx0, &x1, ly0 + 1, &y1, width, height);
856            vp9_blit_line(lx0,  x1, ly0 + 1,  y1, y_buffer, y_stride);
857          } else {
858            vp9_blit_line(lx0,  x1, ly0,  y1, y_buffer, y_stride);
859          }
860        }
861
862        mi++;
863      }
864      mi++;
865    }
866  }
867
868  /* Color in block modes */
869  if ((flags & VP9D_DEBUG_CLR_BLK_MODES)
870      && (ppflags->display_mb_modes_flag || ppflags->display_b_modes_flag)) {
871    int y, x;
872    int width  = ppbuf->y_width;
873    int height = ppbuf->y_height;
874    uint8_t *y_ptr = ppbuf->y_buffer;
875    uint8_t *u_ptr = ppbuf->u_buffer;
876    uint8_t *v_ptr = ppbuf->v_buffer;
877    int y_stride = ppbuf->y_stride;
878    MODE_INFO *mi = cm->mi;
879
880    for (y = 0; y < height; y += 16) {
881      for (x = 0; x < width; x += 16) {
882        int Y = 0, U = 0, V = 0;
883
884        if (mi->mbmi.mode == I4X4_PRED &&
885            ((ppflags->display_mb_modes_flag & I4X4_PRED) ||
886             ppflags->display_b_modes_flag)) {
887          int by, bx;
888          uint8_t *yl, *ul, *vl;
889          union b_mode_info *bmi = mi->bmi;
890
891          yl = y_ptr + x;
892          ul = u_ptr + (x >> 1);
893          vl = v_ptr + (x >> 1);
894
895          for (by = 0; by < 16; by += 4) {
896            for (bx = 0; bx < 16; bx += 4) {
897              if ((ppflags->display_b_modes_flag & (1 << mi->mbmi.mode))
898                  || (ppflags->display_mb_modes_flag & I4X4_PRED)) {
899                Y = B_PREDICTION_MODE_colors[bmi->as_mode][0];
900                U = B_PREDICTION_MODE_colors[bmi->as_mode][1];
901                V = B_PREDICTION_MODE_colors[bmi->as_mode][2];
902
903                vp9_blend_b(yl + bx, ul + (bx >> 1), vl + (bx >> 1), Y, U, V,
904                    0xc000, y_stride);
905              }
906              bmi++;
907            }
908
909            yl += y_stride * 4;
910            ul += y_stride * 1;
911            vl += y_stride * 1;
912          }
913        } else if (ppflags->display_mb_modes_flag & (1 << mi->mbmi.mode)) {
914          Y = MB_PREDICTION_MODE_colors[mi->mbmi.mode][0];
915          U = MB_PREDICTION_MODE_colors[mi->mbmi.mode][1];
916          V = MB_PREDICTION_MODE_colors[mi->mbmi.mode][2];
917
918          vp9_blend_mb_inner(y_ptr + x, u_ptr + (x >> 1), v_ptr + (x >> 1),
919                             Y, U, V, 0xc000, y_stride);
920        }
921
922        mi++;
923      }
924      y_ptr += y_stride * 16;
925      u_ptr += y_stride * 4;
926      v_ptr += y_stride * 4;
927
928      mi++;
929    }
930  }
931
932  /* Color in frame reference blocks */
933  if ((flags & VP9D_DEBUG_CLR_FRM_REF_BLKS) &&
934      ppflags->display_ref_frame_flag) {
935    int y, x;
936    int width  = ppbuf->y_width;
937    int height = ppbuf->y_height;
938    uint8_t *y_ptr = ppbuf->y_buffer;
939    uint8_t *u_ptr = ppbuf->u_buffer;
940    uint8_t *v_ptr = ppbuf->v_buffer;
941    int y_stride = ppbuf->y_stride;
942    MODE_INFO *mi = cm->mi;
943
944    for (y = 0; y < height; y += 16) {
945      for (x = 0; x < width; x += 16) {
946        int Y = 0, U = 0, V = 0;
947
948        if (ppflags->display_ref_frame_flag & (1 << mi->mbmi.ref_frame)) {
949          Y = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][0];
950          U = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][1];
951          V = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][2];
952
953          vp9_blend_mb_outer(y_ptr + x, u_ptr + (x >> 1), v_ptr + (x >> 1),
954                             Y, U, V, 0xc000, y_stride);
955        }
956
957        mi++;
958      }
959      y_ptr += y_stride * 16;
960      u_ptr += y_stride * 4;
961      v_ptr += y_stride * 4;
962
963      mi++;
964    }
965  }
966#endif
967
968  *dest = *ppbuf;
969
970  /* handle problem with extending borders */
971  dest->y_width = cm->width;
972  dest->y_height = cm->height;
973  dest->uv_width = dest->y_width >> cm->subsampling_x;
974  dest->uv_height = dest->y_height >> cm->subsampling_y;
975
976  return 0;
977}
978