Coverage Report

Created: 2024-09-06 07:53

/src/libvpx/vp8/encoder/picklpf.c
Line
Count
Source (jump to first uncovered line)
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 "./vpx_dsp_rtcd.h"
12
#include "./vpx_scale_rtcd.h"
13
#include "vp8/common/onyxc_int.h"
14
#include "onyx_int.h"
15
#include "vp8/encoder/picklpf.h"
16
#include "vp8/encoder/quantize.h"
17
#include "vpx_mem/vpx_mem.h"
18
#include "vpx_scale/vpx_scale.h"
19
#include "vp8/common/alloccommon.h"
20
#include "vp8/common/loopfilter.h"
21
#if VPX_ARCH_ARM
22
#include "vpx_ports/arm.h"
23
#endif
24
25
extern int vp8_calc_ss_err(YV12_BUFFER_CONFIG *source,
26
                           YV12_BUFFER_CONFIG *dest);
27
28
static void yv12_copy_partial_frame(YV12_BUFFER_CONFIG *src_ybc,
29
91
                                    YV12_BUFFER_CONFIG *dst_ybc) {
30
91
  unsigned char *src_y, *dst_y;
31
91
  int yheight;
32
91
  int ystride;
33
91
  int yoffset;
34
91
  int linestocopy;
35
36
91
  yheight = src_ybc->y_height;
37
91
  ystride = src_ybc->y_stride;
38
39
  /* number of MB rows to use in partial filtering */
40
91
  linestocopy = (yheight >> 4) / PARTIAL_FRAME_FRACTION;
41
91
  linestocopy = linestocopy ? linestocopy << 4 : 16; /* 16 lines per MB */
42
43
  /* Copy extra 4 so that full filter context is available if filtering done
44
   * on the copied partial frame and not original. Partial filter does mb
45
   * filtering for top row also, which can modify3 pixels above.
46
   */
47
91
  linestocopy += 4;
48
  /* partial image starts at ~middle of frame (macroblock border)*/
49
91
  yoffset = ystride * (((yheight >> 5) * 16) - 4);
50
91
  src_y = src_ybc->y_buffer + yoffset;
51
91
  dst_y = dst_ybc->y_buffer + yoffset;
52
53
  // The border will be used in vp8_loop_filter_partial_frame so it needs to be
54
  // extended to avoid a valgrind warning.
55
91
  const unsigned char *const top_row = src_ybc->y_buffer;
56
91
  for (int i = yoffset; i < 0; i += ystride, --linestocopy) {
57
0
    memcpy(dst_y, top_row, ystride);
58
0
    dst_y += ystride;
59
0
    src_y += ystride;
60
0
  }
61
91
  memcpy(dst_y, src_y, ystride * linestocopy);
62
91
}
63
64
static int calc_partial_ssl_err(YV12_BUFFER_CONFIG *source,
65
91
                                YV12_BUFFER_CONFIG *dest) {
66
91
  int i, j;
67
91
  int Total = 0;
68
91
  int srcoffset, dstoffset;
69
91
  unsigned char *src = source->y_buffer;
70
91
  unsigned char *dst = dest->y_buffer;
71
72
91
  int linestocopy;
73
74
  /* number of MB rows to use in partial filtering */
75
91
  linestocopy = (source->y_height >> 4) / PARTIAL_FRAME_FRACTION;
76
91
  linestocopy = linestocopy ? linestocopy << 4 : 16; /* 16 lines per MB */
77
78
  /* partial image starts at ~middle of frame (macroblock border)*/
79
91
  srcoffset = source->y_stride * ((dest->y_height >> 5) * 16);
80
91
  dstoffset = dest->y_stride * ((dest->y_height >> 5) * 16);
81
82
91
  src += srcoffset;
83
91
  dst += dstoffset;
84
85
  /* Loop through the Y plane raw and reconstruction data summing
86
   * (square differences)
87
   */
88
705
  for (i = 0; i < linestocopy; i += 16) {
89
11.3k
    for (j = 0; j < source->y_width; j += 16) {
90
10.7k
      unsigned int sse;
91
10.7k
      Total += vpx_mse16x16(src + j, source->y_stride, dst + j, dest->y_stride,
92
10.7k
                            &sse);
93
10.7k
    }
94
95
614
    src += 16 * source->y_stride;
96
614
    dst += 16 * dest->y_stride;
97
614
  }
98
99
91
  return Total;
100
91
}
101
102
/* Enforce a minimum filter level based upon baseline Q */
103
70.0k
static int get_min_filter_level(VP8_COMP *cpi, int base_qindex) {
104
70.0k
  int min_filter_level;
105
106
70.0k
  if (cpi->source_alt_ref_active && cpi->common.refresh_golden_frame &&
107
70.0k
      !cpi->common.refresh_alt_ref_frame) {
108
0
    min_filter_level = 0;
109
70.0k
  } else {
110
70.0k
    if (base_qindex <= 6) {
111
32.4k
      min_filter_level = 0;
112
37.5k
    } else if (base_qindex <= 16) {
113
1.89k
      min_filter_level = 1;
114
35.6k
    } else {
115
35.6k
      min_filter_level = (base_qindex / 8);
116
35.6k
    }
117
70.0k
  }
118
119
70.0k
  return min_filter_level;
120
70.0k
}
121
122
/* Enforce a maximum filter level based upon baseline Q */
123
70.0k
static int get_max_filter_level(VP8_COMP *cpi, int base_qindex) {
124
  /* PGW August 2006: Highest filter values almost always a bad idea */
125
126
  /* jbb chg: 20100118 - not so any more with this overquant stuff allow
127
   * high values with lots of intra coming in.
128
   */
129
70.0k
  int max_filter_level = MAX_LOOP_FILTER;
130
70.0k
  (void)base_qindex;
131
132
70.0k
  if (cpi->twopass.section_intra_rating > 8) {
133
0
    max_filter_level = MAX_LOOP_FILTER * 3 / 4;
134
0
  }
135
136
70.0k
  return max_filter_level;
137
70.0k
}
138
139
20
void vp8cx_pick_filter_level_fast(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi) {
140
20
  VP8_COMMON *cm = &cpi->common;
141
142
20
  int best_err = 0;
143
20
  int filt_err = 0;
144
20
  int min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
145
20
  int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
146
20
  int filt_val;
147
20
  int best_filt_val;
148
20
  YV12_BUFFER_CONFIG *saved_frame = cm->frame_to_show;
149
150
  /* Replace unfiltered frame buffer with a new one */
151
20
  cm->frame_to_show = &cpi->pick_lf_lvl_frame;
152
153
20
  if (cm->frame_type == KEY_FRAME) {
154
0
    cm->sharpness_level = 0;
155
20
  } else {
156
20
    cm->sharpness_level = cpi->oxcf.Sharpness;
157
20
  }
158
159
20
  if (cm->sharpness_level != cm->last_sharpness_level) {
160
0
    vp8_loop_filter_update_sharpness(&cm->lf_info, cm->sharpness_level);
161
0
    cm->last_sharpness_level = cm->sharpness_level;
162
0
  }
163
164
  /* Start the search at the previous frame filter level unless it is
165
   * now out of range.
166
   */
167
20
  if (cm->filter_level < min_filter_level) {
168
7
    cm->filter_level = min_filter_level;
169
13
  } else if (cm->filter_level > max_filter_level) {
170
0
    cm->filter_level = max_filter_level;
171
0
  }
172
173
20
  filt_val = cm->filter_level;
174
20
  best_filt_val = filt_val;
175
176
  /* Get the err using the previous frame's filter value. */
177
178
  /* Copy the unfiltered / processed recon buffer to the new buffer */
179
20
  yv12_copy_partial_frame(saved_frame, cm->frame_to_show);
180
20
  vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
181
182
20
  best_err = calc_partial_ssl_err(sd, cm->frame_to_show);
183
184
20
  filt_val -= 1 + (filt_val > 10);
185
186
  /* Search lower filter levels */
187
21
  while (filt_val >= min_filter_level) {
188
    /* Apply the loop filter */
189
4
    yv12_copy_partial_frame(saved_frame, cm->frame_to_show);
190
4
    vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
191
192
    /* Get the err for filtered frame */
193
4
    filt_err = calc_partial_ssl_err(sd, cm->frame_to_show);
194
195
    /* Update the best case record or exit loop. */
196
4
    if (filt_err < best_err) {
197
1
      best_err = filt_err;
198
1
      best_filt_val = filt_val;
199
3
    } else {
200
3
      break;
201
3
    }
202
203
    /* Adjust filter level */
204
1
    filt_val -= 1 + (filt_val > 10);
205
1
  }
206
207
  /* Search up (note that we have already done filt_val = cm->filter_level) */
208
20
  filt_val = cm->filter_level + 1 + (filt_val > 10);
209
210
20
  if (best_filt_val == cm->filter_level) {
211
    /* Resist raising filter level for very small gains */
212
19
    best_err -= (best_err >> 10);
213
214
67
    while (filt_val < max_filter_level) {
215
      /* Apply the loop filter */
216
67
      yv12_copy_partial_frame(saved_frame, cm->frame_to_show);
217
218
67
      vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
219
220
      /* Get the err for filtered frame */
221
67
      filt_err = calc_partial_ssl_err(sd, cm->frame_to_show);
222
223
      /* Update the best case record or exit loop. */
224
67
      if (filt_err < best_err) {
225
        /* Do not raise filter level if improvement is < 1 part
226
         * in 4096
227
         */
228
48
        best_err = filt_err - (filt_err >> 10);
229
230
48
        best_filt_val = filt_val;
231
48
      } else {
232
19
        break;
233
19
      }
234
235
      /* Adjust filter level */
236
48
      filt_val += 1 + (filt_val > 10);
237
48
    }
238
19
  }
239
240
20
  cm->filter_level = best_filt_val;
241
242
20
  if (cm->filter_level < min_filter_level) cm->filter_level = min_filter_level;
243
244
20
  if (cm->filter_level > max_filter_level) cm->filter_level = max_filter_level;
245
246
  /* restore unfiltered frame pointer */
247
20
  cm->frame_to_show = saved_frame;
248
20
}
249
250
/* Stub function for now Alt LF not used */
251
532k
void vp8cx_set_alt_lf_level(VP8_COMP *cpi, int filt_val) {
252
532k
  MACROBLOCKD *mbd = &cpi->mb.e_mbd;
253
532k
  (void)filt_val;
254
255
532k
  mbd->segment_feature_data[MB_LVL_ALT_LF][0] =
256
532k
      cpi->segment_feature_data[MB_LVL_ALT_LF][0];
257
532k
  mbd->segment_feature_data[MB_LVL_ALT_LF][1] =
258
532k
      cpi->segment_feature_data[MB_LVL_ALT_LF][1];
259
532k
  mbd->segment_feature_data[MB_LVL_ALT_LF][2] =
260
532k
      cpi->segment_feature_data[MB_LVL_ALT_LF][2];
261
532k
  mbd->segment_feature_data[MB_LVL_ALT_LF][3] =
262
532k
      cpi->segment_feature_data[MB_LVL_ALT_LF][3];
263
532k
}
264
265
69.9k
void vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi) {
266
69.9k
  VP8_COMMON *cm = &cpi->common;
267
268
69.9k
  int best_err = 0;
269
69.9k
  int filt_err = 0;
270
69.9k
  int min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
271
69.9k
  int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
272
273
69.9k
  int filter_step;
274
69.9k
  int filt_high = 0;
275
69.9k
  int filt_mid;
276
69.9k
  int filt_low = 0;
277
69.9k
  int filt_best;
278
69.9k
  int filt_direction = 0;
279
280
  /* Bias against raising loop filter and in favor of lowering it */
281
69.9k
  int Bias = 0;
282
283
69.9k
  int ss_err[MAX_LOOP_FILTER + 1];
284
285
69.9k
  YV12_BUFFER_CONFIG *saved_frame = cm->frame_to_show;
286
287
69.9k
  memset(ss_err, 0, sizeof(ss_err));
288
289
  /* Replace unfiltered frame buffer with a new one */
290
69.9k
  cm->frame_to_show = &cpi->pick_lf_lvl_frame;
291
292
69.9k
  if (cm->frame_type == KEY_FRAME) {
293
12.1k
    cm->sharpness_level = 0;
294
57.8k
  } else {
295
57.8k
    cm->sharpness_level = cpi->oxcf.Sharpness;
296
57.8k
  }
297
298
  /* Start the search at the previous frame filter level unless it is
299
   * now out of range.
300
   */
301
69.9k
  filt_mid = cm->filter_level;
302
303
69.9k
  if (filt_mid < min_filter_level) {
304
3.16k
    filt_mid = min_filter_level;
305
66.8k
  } else if (filt_mid > max_filter_level) {
306
0
    filt_mid = max_filter_level;
307
0
  }
308
309
  /* Define the initial step size */
310
69.9k
  filter_step = (filt_mid < 16) ? 4 : filt_mid / 4;
311
312
  /* Get baseline error score */
313
314
  /* Copy the unfiltered / processed recon buffer to the new buffer */
315
69.9k
  vpx_yv12_copy_y(saved_frame, cm->frame_to_show);
316
317
69.9k
  vp8cx_set_alt_lf_level(cpi, filt_mid);
318
69.9k
  vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_mid);
319
320
69.9k
  best_err = vp8_calc_ss_err(sd, cm->frame_to_show);
321
322
69.9k
  ss_err[filt_mid] = best_err;
323
324
69.9k
  filt_best = filt_mid;
325
326
349k
  while (filter_step > 0) {
327
279k
    Bias = (best_err >> (15 - (filt_mid / 8))) * filter_step;
328
329
279k
    if (cpi->twopass.section_intra_rating < 20) {
330
279k
      Bias = Bias * cpi->twopass.section_intra_rating / 20;
331
279k
    }
332
333
279k
    filt_high = ((filt_mid + filter_step) > max_filter_level)
334
279k
                    ? max_filter_level
335
279k
                    : (filt_mid + filter_step);
336
279k
    filt_low = ((filt_mid - filter_step) < min_filter_level)
337
279k
                   ? min_filter_level
338
279k
                   : (filt_mid - filter_step);
339
340
279k
    if ((filt_direction <= 0) && (filt_low != filt_mid)) {
341
197k
      if (ss_err[filt_low] == 0) {
342
        /* Get Low filter error score */
343
172k
        vpx_yv12_copy_y(saved_frame, cm->frame_to_show);
344
172k
        vp8cx_set_alt_lf_level(cpi, filt_low);
345
172k
        vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_low);
346
347
172k
        filt_err = vp8_calc_ss_err(sd, cm->frame_to_show);
348
172k
        ss_err[filt_low] = filt_err;
349
172k
      } else {
350
24.6k
        filt_err = ss_err[filt_low];
351
24.6k
      }
352
353
      /* If value is close to the best so far then bias towards a
354
       * lower loop filter value.
355
       */
356
197k
      if ((filt_err - Bias) < best_err) {
357
        /* Was it actually better than the previous best? */
358
20.4k
        if (filt_err < best_err) best_err = filt_err;
359
360
20.4k
        filt_best = filt_low;
361
20.4k
      }
362
197k
    }
363
364
    /* Now look at filt_high */
365
279k
    if ((filt_direction >= 0) && (filt_high != filt_mid)) {
366
244k
      if (ss_err[filt_high] == 0) {
367
228k
        vpx_yv12_copy_y(saved_frame, cm->frame_to_show);
368
228k
        vp8cx_set_alt_lf_level(cpi, filt_high);
369
228k
        vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_high);
370
371
228k
        filt_err = vp8_calc_ss_err(sd, cm->frame_to_show);
372
228k
        ss_err[filt_high] = filt_err;
373
228k
      } else {
374
16.2k
        filt_err = ss_err[filt_high];
375
16.2k
      }
376
377
      /* Was it better than the previous best? */
378
244k
      if (filt_err < (best_err - Bias)) {
379
33.0k
        best_err = filt_err;
380
33.0k
        filt_best = filt_high;
381
33.0k
      }
382
244k
    }
383
384
    /* Half the step distance if the best filter value was the same
385
     * as last time
386
     */
387
279k
    if (filt_best == filt_mid) {
388
227k
      filter_step = filter_step / 2;
389
227k
      filt_direction = 0;
390
227k
    } else {
391
51.9k
      filt_direction = (filt_best < filt_mid) ? -1 : 1;
392
51.9k
      filt_mid = filt_best;
393
51.9k
    }
394
279k
  }
395
396
69.9k
  cm->filter_level = filt_best;
397
398
  /* restore unfiltered frame pointer */
399
69.9k
  cm->frame_to_show = saved_frame;
400
69.9k
}