vp9_picklpf.c 11.8 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
1
/*
2
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar's avatar
John Koleszar committed
3
 *
4
 *  Use of this source code is governed by a BSD-style license
5 6
 *  that can be found in the LICENSE file in the root of the source
 *  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.
John Koleszar's avatar
John Koleszar committed
9 10 11
 */


12 13 14 15
#include "vp9/common/vp9_onyxc_int.h"
#include "vp9_onyx_int.h"
#include "vp9/encoder/vp9_picklpf.h"
#include "vp9_quantize.h"
John Koleszar's avatar
John Koleszar committed
16 17
#include "vpx_mem/vpx_mem.h"
#include "vpx_scale/vpxscale.h"
18 19
#include "vp9/common/vp9_alloccommon.h"
#include "vp9/common/vp9_loopfilter.h"
20 21 22
#if ARCH_ARM
#include "vpx_ports/arm.h"
#endif
John Koleszar's avatar
John Koleszar committed
23 24 25 26 27 28 29 30 31 32 33

#if HAVE_ARMV7
extern void vp8_yv12_copy_frame_yonly_no_extend_frame_borders_neon(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc);
#endif

#if CONFIG_RUNTIME_CPU_DETECT
#define IF_RTCD(x) (x)
#else
#define IF_RTCD(x) NULL
#endif

34 35
void vp9_yv12_copy_partial_frame_c(YV12_BUFFER_CONFIG *src_ybc,
                                   YV12_BUFFER_CONFIG *dst_ybc, int Fraction) {
John Koleszar's avatar
John Koleszar committed
36 37 38 39 40 41
  unsigned char *src_y, *dst_y;
  int yheight;
  int ystride;
  int border;
  int yoffset;
  int linestocopy;
John Koleszar's avatar
John Koleszar committed
42

John Koleszar's avatar
John Koleszar committed
43 44 45
  border   = src_ybc->border;
  yheight  = src_ybc->y_height;
  ystride  = src_ybc->y_stride;
John Koleszar's avatar
John Koleszar committed
46

John Koleszar's avatar
John Koleszar committed
47
  linestocopy = (yheight >> (Fraction + 4));
John Koleszar's avatar
John Koleszar committed
48

John Koleszar's avatar
John Koleszar committed
49 50
  if (linestocopy < 1)
    linestocopy = 1;
John Koleszar's avatar
John Koleszar committed
51

John Koleszar's avatar
John Koleszar committed
52
  linestocopy <<= 4;
John Koleszar's avatar
John Koleszar committed
53

John Koleszar's avatar
John Koleszar committed
54 55 56
  yoffset  = ystride * ((yheight >> 5) * 16 - 8);
  src_y = src_ybc->y_buffer + yoffset;
  dst_y = dst_ybc->y_buffer + yoffset;
John Koleszar's avatar
John Koleszar committed
57

John Koleszar's avatar
John Koleszar committed
58
  vpx_memcpy(dst_y, src_y, ystride * (linestocopy + 16));
John Koleszar's avatar
John Koleszar committed
59
}
60

61 62
static int calc_partial_ssl_err(YV12_BUFFER_CONFIG *source,
                                YV12_BUFFER_CONFIG *dest, int Fraction) {
John Koleszar's avatar
John Koleszar committed
63 64 65 66 67
  int i, j;
  int Total = 0;
  int srcoffset, dstoffset;
  unsigned char *src = source->y_buffer;
  unsigned char *dst = dest->y_buffer;
John Koleszar's avatar
John Koleszar committed
68

John Koleszar's avatar
John Koleszar committed
69
  int linestocopy = (source->y_height >> (Fraction + 4));
John Koleszar's avatar
John Koleszar committed
70

John Koleszar's avatar
John Koleszar committed
71 72
  if (linestocopy < 1)
    linestocopy = 1;
John Koleszar's avatar
John Koleszar committed
73

John Koleszar's avatar
John Koleszar committed
74
  linestocopy <<= 4;
John Koleszar's avatar
John Koleszar committed
75 76


John Koleszar's avatar
John Koleszar committed
77 78
  srcoffset = source->y_stride   * (dest->y_height >> 5) * 16;
  dstoffset = dest->y_stride     * (dest->y_height >> 5) * 16;
John Koleszar's avatar
John Koleszar committed
79

John Koleszar's avatar
John Koleszar committed
80 81
  src += srcoffset;
  dst += dstoffset;
John Koleszar's avatar
John Koleszar committed
82

John Koleszar's avatar
John Koleszar committed
83 84 85 86
  // Loop through the Y plane raw and reconstruction data summing (square differences)
  for (i = 0; i < linestocopy; i += 16) {
    for (j = 0; j < source->y_width; j += 16) {
      unsigned int sse;
87
      Total += vp9_mse16x16(src + j, source->y_stride, dst + j, dest->y_stride,
88
                            &sse);
John Koleszar's avatar
John Koleszar committed
89 90
    }

John Koleszar's avatar
John Koleszar committed
91 92 93 94 95
    src += 16 * source->y_stride;
    dst += 16 * dest->y_stride;
  }

  return Total;
John Koleszar's avatar
John Koleszar committed
96 97 98
}

// Enforce a minimum filter level based upon baseline Q
99
static int get_min_filter_level(VP9_COMP *cpi, int base_qindex) {
John Koleszar's avatar
John Koleszar committed
100
  int min_filter_level;
101
  /*int q = (int) vp9_convert_qindex_to_q(base_qindex);
John Koleszar's avatar
John Koleszar committed
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117

  if (cpi->source_alt_ref_active && cpi->common.refresh_golden_frame && !cpi->common.refresh_alt_ref_frame)
      min_filter_level = 0;
  else
  {
      if (q <= 10)
          min_filter_level = 0;
      else if (q <= 64)
          min_filter_level = 1;
      else
          min_filter_level = (q >> 6);
  }
  */
  min_filter_level = 0;

  return min_filter_level;
John Koleszar's avatar
John Koleszar committed
118 119 120
}

// Enforce a maximum filter level based upon baseline Q
121
static int get_max_filter_level(VP9_COMP *cpi, int base_qindex) {
John Koleszar's avatar
John Koleszar committed
122
  // PGW August 2006: Highest filter values almost always a bad idea
John Koleszar's avatar
John Koleszar committed
123

John Koleszar's avatar
John Koleszar committed
124 125 126 127
  // jbb chg: 20100118 - not so any more with this overquant stuff allow high values
  // with lots of intra coming in.
  int max_filter_level = MAX_LOOP_FILTER;// * 3 / 4;
  (void)base_qindex;
John Koleszar's avatar
John Koleszar committed
128

John Koleszar's avatar
John Koleszar committed
129 130
  if (cpi->twopass.section_intra_rating > 8)
    max_filter_level = MAX_LOOP_FILTER * 3 / 4;
John Koleszar's avatar
John Koleszar committed
131

John Koleszar's avatar
John Koleszar committed
132
  return max_filter_level;
John Koleszar's avatar
John Koleszar committed
133 134
}

135 136
void vp9_pick_filter_level_fast(YV12_BUFFER_CONFIG *sd, VP9_COMP *cpi) {
  VP9_COMMON *cm = &cpi->common;
Johann's avatar
Johann committed
137

John Koleszar's avatar
John Koleszar committed
138 139 140 141 142 143
  int best_err = 0;
  int filt_err = 0;
  int min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
  int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
  int filt_val;
  int best_filt_val = cm->filter_level;
John Koleszar's avatar
John Koleszar committed
144

John Koleszar's avatar
John Koleszar committed
145
  //  Make a copy of the unfiltered / processed recon buffer
146
  vp9_yv12_copy_partial_frame(cm->frame_to_show, &cpi->last_frame_uf, 3);
John Koleszar's avatar
John Koleszar committed
147

John Koleszar's avatar
John Koleszar committed
148 149 150 151
  if (cm->frame_type == KEY_FRAME)
    cm->sharpness_level = 0;
  else
    cm->sharpness_level = cpi->oxcf.Sharpness;
John Koleszar's avatar
John Koleszar committed
152

John Koleszar's avatar
John Koleszar committed
153
  if (cm->sharpness_level != cm->last_sharpness_level) {
154
    vp9_loop_filter_update_sharpness(&cm->lf_info, cm->sharpness_level);
John Koleszar's avatar
John Koleszar committed
155 156
    cm->last_sharpness_level = cm->sharpness_level;
  }
John Koleszar's avatar
John Koleszar committed
157

John Koleszar's avatar
John Koleszar committed
158 159 160 161 162
  // Start the search at the previous frame filter level unless it is now out of range.
  if (cm->filter_level < min_filter_level)
    cm->filter_level = min_filter_level;
  else if (cm->filter_level > max_filter_level)
    cm->filter_level = max_filter_level;
John Koleszar's avatar
John Koleszar committed
163

John Koleszar's avatar
John Koleszar committed
164 165
  filt_val = cm->filter_level;
  best_filt_val = filt_val;
John Koleszar's avatar
John Koleszar committed
166

John Koleszar's avatar
John Koleszar committed
167
  // Get the err using the previous frame's filter value.
168
  vp9_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
John Koleszar's avatar
John Koleszar committed
169

170
  best_err = calc_partial_ssl_err(sd, cm->frame_to_show, 3);
John Koleszar's avatar
John Koleszar committed
171

John Koleszar's avatar
John Koleszar committed
172
  //  Re-instate the unfiltered frame
173
  vp9_yv12_copy_partial_frame(&cpi->last_frame_uf, cm->frame_to_show, 3);
John Koleszar's avatar
John Koleszar committed
174

John Koleszar's avatar
John Koleszar committed
175
  filt_val -= (1 + ((filt_val > 10) ? 1 : 0));
John Koleszar's avatar
John Koleszar committed
176

John Koleszar's avatar
John Koleszar committed
177 178 179
  // Search lower filter levels
  while (filt_val >= min_filter_level) {
    // Apply the loop filter
180
    vp9_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
John Koleszar's avatar
John Koleszar committed
181 182

    // Get the err for filtered frame
183
    filt_err = calc_partial_ssl_err(sd, cm->frame_to_show, 3);
John Koleszar's avatar
John Koleszar committed
184 185

    //  Re-instate the unfiltered frame
186
    vp9_yv12_copy_partial_frame(&cpi->last_frame_uf, cm->frame_to_show, 3);
John Koleszar's avatar
John Koleszar committed
187 188


John Koleszar's avatar
John Koleszar committed
189 190 191 192 193 194 195 196 197 198
    // Update the best case record or exit loop.
    if (filt_err < best_err) {
      best_err = filt_err;
      best_filt_val = filt_val;
    } else
      break;

    // Adjust filter level
    filt_val -= (1 + ((filt_val > 10) ? 1 : 0));
  }
John Koleszar's avatar
John Koleszar committed
199

John Koleszar's avatar
John Koleszar committed
200 201
  // Search up (note that we have already done filt_val = cm->filter_level)
  filt_val = cm->filter_level + (1 + ((filt_val > 10) ? 1 : 0));
John Koleszar's avatar
John Koleszar committed
202

John Koleszar's avatar
John Koleszar committed
203 204 205
  if (best_filt_val == cm->filter_level) {
    // Resist raising filter level for very small gains
    best_err -= (best_err >> 10);
John Koleszar's avatar
John Koleszar committed
206

John Koleszar's avatar
John Koleszar committed
207 208
    while (filt_val < max_filter_level) {
      // Apply the loop filter
209
      vp9_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
John Koleszar's avatar
John Koleszar committed
210

John Koleszar's avatar
John Koleszar committed
211
      // Get the err for filtered frame
212
      filt_err = calc_partial_ssl_err(sd, cm->frame_to_show, 3);
John Koleszar's avatar
John Koleszar committed
213

John Koleszar's avatar
John Koleszar committed
214
      //  Re-instate the unfiltered frame
215
      vp9_yv12_copy_partial_frame(&cpi->last_frame_uf,
216
                                      cm->frame_to_show, 3);
John Koleszar's avatar
John Koleszar committed
217

John Koleszar's avatar
John Koleszar committed
218 219 220 221 222 223 224 225 226 227 228
      // Update the best case record or exit loop.
      if (filt_err < best_err) {
        // Do not raise filter level if improvement is < 1 part in 4096
        best_err = filt_err - (filt_err >> 10);

        best_filt_val = filt_val;
      } else
        break;

      // Adjust filter level
      filt_val += (1 + ((filt_val > 10) ? 1 : 0));
John Koleszar's avatar
John Koleszar committed
229
    }
John Koleszar's avatar
John Koleszar committed
230
  }
John Koleszar's avatar
John Koleszar committed
231

John Koleszar's avatar
John Koleszar committed
232
  cm->filter_level = best_filt_val;
John Koleszar's avatar
John Koleszar committed
233

John Koleszar's avatar
John Koleszar committed
234 235
  if (cm->filter_level < min_filter_level)
    cm->filter_level = min_filter_level;
John Koleszar's avatar
John Koleszar committed
236

John Koleszar's avatar
John Koleszar committed
237 238
  if (cm->filter_level > max_filter_level)
    cm->filter_level = max_filter_level;
John Koleszar's avatar
John Koleszar committed
239 240 241
}

// Stub function for now Alt LF not used
242
void vp9_set_alt_lf_level(VP9_COMP *cpi, int filt_val) {
243
}
John Koleszar's avatar
John Koleszar committed
244

245 246
void vp9_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP9_COMP *cpi) {
  VP9_COMMON *cm = &cpi->common;
John Koleszar's avatar
John Koleszar committed
247

John Koleszar's avatar
John Koleszar committed
248 249 250 251
  int best_err = 0;
  int filt_err = 0;
  int min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
  int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
John Koleszar's avatar
John Koleszar committed
252

John Koleszar's avatar
John Koleszar committed
253 254 255 256 257 258
  int filter_step;
  int filt_high = 0;
  int filt_mid = cm->filter_level;      // Start search at previous frame filter level
  int filt_low = 0;
  int filt_best;
  int filt_direction = 0;
John Koleszar's avatar
John Koleszar committed
259

John Koleszar's avatar
John Koleszar committed
260
  int Bias = 0;                       // Bias against raising loop filter and in favour of lowering it
John Koleszar's avatar
John Koleszar committed
261

John Koleszar's avatar
John Koleszar committed
262
  //  Make a copy of the unfiltered / processed recon buffer
John Koleszar's avatar
John Koleszar committed
263
#if HAVE_ARMV7
264
#if CONFIG_RUNTIME_CPU_DETECT
John Koleszar's avatar
John Koleszar committed
265
  if (cm->rtcd.flags & HAS_NEON)
266
#endif
John Koleszar's avatar
John Koleszar committed
267 268 269
  {
    vp8_yv12_copy_frame_yonly_no_extend_frame_borders_neon(cm->frame_to_show, &cpi->last_frame_uf);
  }
270
#if CONFIG_RUNTIME_CPU_DETECT
John Koleszar's avatar
John Koleszar committed
271
  else
272 273 274
#endif
#endif
#if !HAVE_ARMV7 || CONFIG_RUNTIME_CPU_DETECT
John Koleszar's avatar
John Koleszar committed
275
  {
John Koleszar's avatar
John Koleszar committed
276
    vp8_yv12_copy_frame(cm->frame_to_show, &cpi->last_frame_uf);
John Koleszar's avatar
John Koleszar committed
277
  }
John Koleszar's avatar
John Koleszar committed
278 279
#endif

John Koleszar's avatar
John Koleszar committed
280 281 282 283
  if (cm->frame_type == KEY_FRAME)
    cm->sharpness_level = 0;
  else
    cm->sharpness_level = cpi->oxcf.Sharpness;
John Koleszar's avatar
John Koleszar committed
284

John Koleszar's avatar
John Koleszar committed
285 286
  // Start the search at the previous frame filter level unless it is now out of range.
  filt_mid = cm->filter_level;
John Koleszar's avatar
John Koleszar committed
287

John Koleszar's avatar
John Koleszar committed
288 289 290 291
  if (filt_mid < min_filter_level)
    filt_mid = min_filter_level;
  else if (filt_mid > max_filter_level)
    filt_mid = max_filter_level;
John Koleszar's avatar
John Koleszar committed
292

John Koleszar's avatar
John Koleszar committed
293 294
  // Define the initial step size
  filter_step = (filt_mid < 16) ? 4 : filt_mid / 4;
John Koleszar's avatar
John Koleszar committed
295

John Koleszar's avatar
John Koleszar committed
296
  // Get baseline error score
297
  vp9_set_alt_lf_level(cpi, filt_mid);
298
  vp9_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_mid);
John Koleszar's avatar
John Koleszar committed
299

300
  best_err = vp9_calc_ss_err(sd, cm->frame_to_show);
John Koleszar's avatar
John Koleszar committed
301
  filt_best = filt_mid;
John Koleszar's avatar
John Koleszar committed
302

John Koleszar's avatar
John Koleszar committed
303
  //  Re-instate the unfiltered frame
John Koleszar's avatar
John Koleszar committed
304
#if HAVE_ARMV7
305
#if CONFIG_RUNTIME_CPU_DETECT
John Koleszar's avatar
John Koleszar committed
306
  if (cm->rtcd.flags & HAS_NEON)
307
#endif
John Koleszar's avatar
John Koleszar committed
308 309 310
  {
    vp8_yv12_copy_frame_yonly_no_extend_frame_borders_neon(&cpi->last_frame_uf, cm->frame_to_show);
  }
311
#if CONFIG_RUNTIME_CPU_DETECT
John Koleszar's avatar
John Koleszar committed
312
  else
313 314 315
#endif
#endif
#if !HAVE_ARMV7 || CONFIG_RUNTIME_CPU_DETECT
John Koleszar's avatar
John Koleszar committed
316
  {
John Koleszar's avatar
John Koleszar committed
317
    vp8_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show);
John Koleszar's avatar
John Koleszar committed
318
  }
John Koleszar's avatar
John Koleszar committed
319 320
#endif

John Koleszar's avatar
John Koleszar committed
321 322
  while (filter_step > 0) {
    Bias = (best_err >> (15 - (filt_mid / 8))) * filter_step; // PGW change 12/12/06 for small images
John Koleszar's avatar
John Koleszar committed
323

John Koleszar's avatar
John Koleszar committed
324 325 326
    // jbb chg: 20100118 - in sections with lots of new material coming in don't bias as much to a low filter value
    if (cpi->twopass.section_intra_rating < 20)
      Bias = Bias * cpi->twopass.section_intra_rating / 20;
John Koleszar's avatar
John Koleszar committed
327

John Koleszar's avatar
John Koleszar committed
328
    // yx, bias less for large block size
329
    if (cpi->common.txfm_mode != ONLY_4X4)
John Koleszar's avatar
John Koleszar committed
330
      Bias >>= 1;
331

John Koleszar's avatar
John Koleszar committed
332 333
    filt_high = ((filt_mid + filter_step) > max_filter_level) ? max_filter_level : (filt_mid + filter_step);
    filt_low = ((filt_mid - filter_step) < min_filter_level) ? min_filter_level : (filt_mid - filter_step);
John Koleszar's avatar
John Koleszar committed
334

John Koleszar's avatar
John Koleszar committed
335 336
    if ((filt_direction <= 0) && (filt_low != filt_mid)) {
      // Get Low filter error score
337
      vp9_set_alt_lf_level(cpi, filt_low);
338
      vp9_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_low);
John Koleszar's avatar
John Koleszar committed
339

340
      filt_err = vp9_calc_ss_err(sd, cm->frame_to_show);
John Koleszar's avatar
John Koleszar committed
341

John Koleszar's avatar
John Koleszar committed
342
      //  Re-instate the unfiltered frame
John Koleszar's avatar
John Koleszar committed
343
#if HAVE_ARMV7
344
#if CONFIG_RUNTIME_CPU_DETECT
John Koleszar's avatar
John Koleszar committed
345
      if (cm->rtcd.flags & HAS_NEON)
346
#endif
John Koleszar's avatar
John Koleszar committed
347 348 349
      {
        vp8_yv12_copy_frame_yonly_no_extend_frame_borders_neon(&cpi->last_frame_uf, cm->frame_to_show);
      }
350
#if CONFIG_RUNTIME_CPU_DETECT
John Koleszar's avatar
John Koleszar committed
351
      else
352 353 354
#endif
#endif
#if !HAVE_ARMV7 || CONFIG_RUNTIME_CPU_DETECT
John Koleszar's avatar
John Koleszar committed
355
      {
John Koleszar's avatar
John Koleszar committed
356
        vp8_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show);
John Koleszar's avatar
John Koleszar committed
357
      }
John Koleszar's avatar
John Koleszar committed
358 359
#endif

John Koleszar's avatar
John Koleszar committed
360 361 362 363 364
      // If value is close to the best so far then bias towards a lower loop filter value.
      if ((filt_err - Bias) < best_err) {
        // Was it actually better than the previous best?
        if (filt_err < best_err)
          best_err = filt_err;
John Koleszar's avatar
John Koleszar committed
365

John Koleszar's avatar
John Koleszar committed
366 367 368
        filt_best = filt_low;
      }
    }
John Koleszar's avatar
John Koleszar committed
369

John Koleszar's avatar
John Koleszar committed
370 371
    // Now look at filt_high
    if ((filt_direction >= 0) && (filt_high != filt_mid)) {
372
      vp9_set_alt_lf_level(cpi, filt_high);
373
      vp9_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_high);
John Koleszar's avatar
John Koleszar committed
374

375
      filt_err = vp9_calc_ss_err(sd, cm->frame_to_show);
John Koleszar's avatar
John Koleszar committed
376

John Koleszar's avatar
John Koleszar committed
377
      //  Re-instate the unfiltered frame
John Koleszar's avatar
John Koleszar committed
378
#if HAVE_ARMV7
379
#if CONFIG_RUNTIME_CPU_DETECT
John Koleszar's avatar
John Koleszar committed
380
      if (cm->rtcd.flags & HAS_NEON)
381
#endif
John Koleszar's avatar
John Koleszar committed
382 383 384
      {
        vp8_yv12_copy_frame_yonly_no_extend_frame_borders_neon(&cpi->last_frame_uf, cm->frame_to_show);
      }
385
#if CONFIG_RUNTIME_CPU_DETECT
John Koleszar's avatar
John Koleszar committed
386
      else
387 388 389
#endif
#endif
#if !HAVE_ARMV7 || CONFIG_RUNTIME_CPU_DETECT
John Koleszar's avatar
John Koleszar committed
390
      {
John Koleszar's avatar
John Koleszar committed
391
        vp8_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show);
John Koleszar's avatar
John Koleszar committed
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
      }
#endif

      // Was it better than the previous best?
      if (filt_err < (best_err - Bias)) {
        best_err = filt_err;
        filt_best = filt_high;
      }
    }

    // Half the step distance if the best filter value was the same as last time
    if (filt_best == filt_mid) {
      filter_step = filter_step / 2;
      filt_direction = 0;
    } else {
      filt_direction = (filt_best < filt_mid) ? -1 : 1;
      filt_mid = filt_best;
John Koleszar's avatar
John Koleszar committed
409
    }
John Koleszar's avatar
John Koleszar committed
410
  }
John Koleszar's avatar
John Koleszar committed
411

John Koleszar's avatar
John Koleszar committed
412
  cm->filter_level = filt_best;
John Koleszar's avatar
John Koleszar committed
413
}
414