vp9_denoiser.c 5.46 KB
Newer Older
Tim Kopp's avatar
Tim Kopp committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
 *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <stdio.h>
#include <stdint.h>
#include "vp9/encoder/vp9_denoiser.h"
#include "vpx_scale/yv12config.h"

static const int widths[]  = {4, 4, 8, 8,  8, 16, 16, 16, 32, 32, 32, 64, 64};
static const int heights[] = {4, 8, 4, 8, 16,  8, 16, 32, 16, 32, 64, 32, 64};

int vp9_denoiser_filter() {
  return 0;
}

Tim Kopp's avatar
Tim Kopp committed
23
24
int update_running_avg(uint8_t *mc_avg, int mc_avg_stride, uint8_t *avg,
                       int avg_stride, uint8_t *sig, int sig_stride,
25
                       int increase_denoising, BLOCK_SIZE bs) {
Tim Kopp's avatar
Tim Kopp committed
26
  int r, c;
27
28
29
  int diff, adj, absdiff;
  int shift_inc1 = 0, shift_inc2 = 1;
  int adj_val[] = {3, 4, 6};
Tim Kopp's avatar
Tim Kopp committed
30
31
  int total_adj = 0;

32
33
34
35
36
  if (increase_denoising) {
    shift_inc1 = 1;
    shift_inc2 = 2;
  }

Tim Kopp's avatar
Tim Kopp committed
37
38
39
  for (r = 0; r < heights[bs]; ++r) {
    for (c = 0; c < widths[bs]; ++c) {
      diff = mc_avg[c] - sig[c];
40
      absdiff = abs(diff);
Tim Kopp's avatar
Tim Kopp committed
41

42
43
44
      if (absdiff <= 3 + shift_inc1) {
        avg[c] = mc_avg[c];
        total_adj += diff;
Tim Kopp's avatar
Tim Kopp committed
45
      } else {
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
        switch (absdiff) {
          case 4: case 5: case 6: case 7:
            adj = adj_val[0];
          case 8: case 9: case 10: case 11:
          case 12: case 13: case 14: case 15:
            adj = adj_val[1];
          default:
            adj = adj_val[2];
        }
        if (diff > 0) {
          avg[c] = MIN(UINT8_MAX, sig[c] + adj);
          total_adj += adj;
        } else {
          avg[c] = MAX(0, sig[c] - adj);
          total_adj -= adj;
        }
Tim Kopp's avatar
Tim Kopp committed
62
63
64
65
66
67
68
69
70
      }
    }
    sig += sig_stride;
    avg += avg_stride;
    mc_avg += mc_avg_stride;
  }
  return total_adj;
}

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
uint8_t *block_start(uint8_t *framebuf, int stride, int mi_row, int mi_col) {
  return framebuf + (stride * mi_row) + mi_col;
}

void copy_block(uint8_t *dest, int dest_stride,
                uint8_t *src, int src_stride, BLOCK_SIZE bs) {
  int r, c;
  for (r = 0; r < heights[bs]; ++r) {
    for (c = 0; c < widths[bs]; ++c) {
      dest[c] = src[c];
    }
    dest += dest_stride;
    src += src_stride;
  }
  return;
}

Tim Kopp's avatar
Tim Kopp committed
88
89
90
void vp9_denoiser_denoise(VP9_DENOISER *denoiser,
                          MACROBLOCK *mb, MODE_INFO **grid,
                          int mi_row, int mi_col, BLOCK_SIZE bs) {
91
92
93
94
95
  int decision = COPY_BLOCK;

  YV12_BUFFER_CONFIG avg = denoiser->running_avg_y[INTRA_FRAME];
  struct buf_2d src = mb->plane[0].src;

96
97
98
99
  update_running_avg(denoiser->mc_running_avg_y.y_buffer,
                     denoiser->mc_running_avg_y.y_stride,
                     denoiser->running_avg_y[INTRA_FRAME].y_buffer,
                     denoiser->running_avg_y[INTRA_FRAME].y_stride,
100
                     mb->plane[0].src.buf, mb->plane[0].src.stride, 0, bs);
101
102
103
104
105
106
107
108
109
110

  if (decision == FILTER_BLOCK) {
  }
  if (decision == COPY_BLOCK) {
    copy_block(block_start(avg.y_buffer, avg.y_stride, mi_row, mi_col),
               avg.y_stride,
               block_start(src.buf, src.stride, mi_row, mi_col),
               src.stride,
               bs);
  }
Tim Kopp's avatar
Tim Kopp committed
111
112
113
  return;
}

114
115
116
117
void copy_frame(YV12_BUFFER_CONFIG dest, YV12_BUFFER_CONFIG src) {
  memcpy(dest.buffer_alloc, src.buffer_alloc, src.buffer_alloc_sz);
}

Tim Kopp's avatar
Tim Kopp committed
118
void vp9_denoiser_update_frame_info(VP9_DENOISER *denoiser,
119
                                    YV12_BUFFER_CONFIG src,
Tim Kopp's avatar
Tim Kopp committed
120
121
122
123
                                    FRAME_TYPE frame_type,
                                    int refresh_alt_ref_frame,
                                    int refresh_golden_frame,
                                    int refresh_last_frame) {
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
  int i;
  if (frame_type == KEY_FRAME) {
    copy_frame(denoiser->running_avg_y[LAST_FRAME], src);
    for (i = 2; i < MAX_REF_FRAMES - 1; i++) {
      copy_frame(denoiser->running_avg_y[i],
                 denoiser->running_avg_y[LAST_FRAME]);
    }
  } else { /* For non key frames */
    if (refresh_alt_ref_frame) {
      copy_frame(denoiser->running_avg_y[ALTREF_FRAME],
                 denoiser->running_avg_y[INTRA_FRAME]);
    }
    if (refresh_golden_frame) {
      copy_frame(denoiser->running_avg_y[GOLDEN_FRAME],
                 denoiser->running_avg_y[INTRA_FRAME]);
    }
    if (refresh_last_frame) {
      copy_frame(denoiser->running_avg_y[LAST_FRAME],
                 denoiser->running_avg_y[INTRA_FRAME]);
    }
  }

Tim Kopp's avatar
Tim Kopp committed
146
147
148
149
150
151
152
153
  return;
}

void vp9_denoiser_update_frame_stats() {
  return;
}

int vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height,
154
155
                       int ssx, int ssy, int border) {
  int i, fail;
156
157
  assert(denoiser);

158
159
160
161
162
163
164
  for (i = 0; i < MAX_REF_FRAMES; ++i) {
    fail = vp9_alloc_frame_buffer(&denoiser->running_avg_y[i], width, height,
                                ssx, ssy, border);
    if (fail) {
      vp9_denoiser_free(denoiser);
      return 1;
    }
165
166
  }

167
168
169
  fail = vp9_alloc_frame_buffer(&denoiser->mc_running_avg_y, width, height,
                              ssx, ssy, border);
  if (fail) {
170
171
172
173
    vp9_denoiser_free(denoiser);
    return 1;
  }

Tim Kopp's avatar
Tim Kopp committed
174
175
176
177
  return 0;
}

void vp9_denoiser_free(VP9_DENOISER *denoiser) {
178
179
180
181
182
  int i;
  for (i = 0; i < MAX_REF_FRAMES; ++i) {
    if (&denoiser->running_avg_y[i] != NULL) {
      vp9_free_frame_buffer(&denoiser->running_avg_y[i]);
    }
183
  }
184
185
  if (&denoiser->mc_running_avg_y != NULL) {
    vp9_free_frame_buffer(&denoiser->mc_running_avg_y);
186
  }
Tim Kopp's avatar
Tim Kopp committed
187
188
189
  return;
}