media/libvpx/vp9/encoder/vp9_vaq.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/libvpx/vp9/encoder/vp9_vaq.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,147 @@
     1.4 +/*
     1.5 + *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
     1.6 + *
     1.7 + *  Use of this source code is governed by a BSD-style license
     1.8 + *  that can be found in the LICENSE file in the root of the source
     1.9 + *  tree. An additional intellectual property rights grant can be found
    1.10 + *  in the file PATENTS.  All contributing project authors may
    1.11 + *  be found in the AUTHORS file in the root of the source tree.
    1.12 + */
    1.13 +
    1.14 +#include <math.h>
    1.15 +
    1.16 +#include "vp9/encoder/vp9_vaq.h"
    1.17 +
    1.18 +#include "vp9/common/vp9_seg_common.h"
    1.19 +
    1.20 +#include "vp9/encoder/vp9_ratectrl.h"
    1.21 +#include "vp9/encoder/vp9_rdopt.h"
    1.22 +#include "vp9/encoder/vp9_segmentation.h"
    1.23 +#include "vp9/common/vp9_systemdependent.h"
    1.24 +
    1.25 +#define ENERGY_MIN (-3)
    1.26 +#define ENERGY_MAX (3)
    1.27 +#define ENERGY_SPAN (ENERGY_MAX - ENERGY_MIN +  1)
    1.28 +#define ENERGY_IN_BOUNDS(energy)\
    1.29 +  assert((energy) >= ENERGY_MIN && (energy) <= ENERGY_MAX)
    1.30 +
    1.31 +static double q_ratio[MAX_SEGMENTS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
    1.32 +static double rdmult_ratio[MAX_SEGMENTS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
    1.33 +static int segment_id[MAX_SEGMENTS] = { 5, 3, 1, 0, 2, 4, 6, 7 };
    1.34 +
    1.35 +#define Q_RATIO(i) q_ratio[(i) - ENERGY_MIN]
    1.36 +#define RDMULT_RATIO(i) rdmult_ratio[(i) - ENERGY_MIN]
    1.37 +#define SEGMENT_ID(i) segment_id[(i) - ENERGY_MIN]
    1.38 +
    1.39 +DECLARE_ALIGNED(16, static const uint8_t, vp9_64_zeros[64]) = {0};
    1.40 +
    1.41 +unsigned int vp9_vaq_segment_id(int energy) {
    1.42 +  ENERGY_IN_BOUNDS(energy);
    1.43 +
    1.44 +  return SEGMENT_ID(energy);
    1.45 +}
    1.46 +
    1.47 +double vp9_vaq_rdmult_ratio(int energy) {
    1.48 +  ENERGY_IN_BOUNDS(energy);
    1.49 +
    1.50 +  vp9_clear_system_state();  // __asm emms;
    1.51 +
    1.52 +  return RDMULT_RATIO(energy);
    1.53 +}
    1.54 +
    1.55 +double vp9_vaq_inv_q_ratio(int energy) {
    1.56 +  ENERGY_IN_BOUNDS(energy);
    1.57 +
    1.58 +  vp9_clear_system_state();  // __asm emms;
    1.59 +
    1.60 +  return Q_RATIO(-energy);
    1.61 +}
    1.62 +
    1.63 +void vp9_vaq_init() {
    1.64 +  int i;
    1.65 +  double base_ratio;
    1.66 +
    1.67 +  assert(ENERGY_SPAN <= MAX_SEGMENTS);
    1.68 +
    1.69 +  vp9_clear_system_state();  // __asm emms;
    1.70 +
    1.71 +  base_ratio = 1.8;
    1.72 +
    1.73 +  for (i = ENERGY_MIN; i <= ENERGY_MAX; i++) {
    1.74 +    Q_RATIO(i) = pow(base_ratio, i/3.0);
    1.75 +  }
    1.76 +}
    1.77 +
    1.78 +void vp9_vaq_frame_setup(VP9_COMP *cpi) {
    1.79 +  VP9_COMMON *cm = &cpi->common;
    1.80 +  struct segmentation *seg = &cm->seg;
    1.81 +  int base_q = vp9_convert_qindex_to_q(cm->base_qindex);
    1.82 +  int base_rdmult = vp9_compute_rd_mult(cpi, cm->base_qindex +
    1.83 +                                        cm->y_dc_delta_q);
    1.84 +  int i;
    1.85 +
    1.86 +  vp9_enable_segmentation((VP9_PTR)cpi);
    1.87 +  vp9_clearall_segfeatures(seg);
    1.88 +
    1.89 +  seg->abs_delta = SEGMENT_DELTADATA;
    1.90 +
    1.91 +  vp9_clear_system_state();  // __asm emms;
    1.92 +
    1.93 +  for (i = ENERGY_MIN; i <= ENERGY_MAX; i++) {
    1.94 +    int qindex_delta, segment_rdmult;
    1.95 +
    1.96 +    if (Q_RATIO(i) == 1) {
    1.97 +      // No need to enable SEG_LVL_ALT_Q for this segment
    1.98 +      RDMULT_RATIO(i) = 1;
    1.99 +      continue;
   1.100 +    }
   1.101 +
   1.102 +    qindex_delta = vp9_compute_qdelta(cpi, base_q, base_q * Q_RATIO(i));
   1.103 +    vp9_set_segdata(seg, SEGMENT_ID(i), SEG_LVL_ALT_Q, qindex_delta);
   1.104 +    vp9_enable_segfeature(seg, SEGMENT_ID(i), SEG_LVL_ALT_Q);
   1.105 +
   1.106 +    segment_rdmult = vp9_compute_rd_mult(cpi, cm->base_qindex + qindex_delta +
   1.107 +                                         cm->y_dc_delta_q);
   1.108 +
   1.109 +    RDMULT_RATIO(i) = (double) segment_rdmult / base_rdmult;
   1.110 +  }
   1.111 +}
   1.112 +
   1.113 +
   1.114 +static unsigned int block_variance(VP9_COMP *cpi, MACROBLOCK *x,
   1.115 +                                   BLOCK_SIZE bs) {
   1.116 +  MACROBLOCKD *xd = &x->e_mbd;
   1.117 +  unsigned int var, sse;
   1.118 +  int right_overflow = (xd->mb_to_right_edge < 0) ?
   1.119 +      ((-xd->mb_to_right_edge) >> 3) : 0;
   1.120 +  int bottom_overflow = (xd->mb_to_bottom_edge < 0) ?
   1.121 +      ((-xd->mb_to_bottom_edge) >> 3) : 0;
   1.122 +
   1.123 +  if (right_overflow || bottom_overflow) {
   1.124 +    const int bw = 8 * num_8x8_blocks_wide_lookup[bs] - right_overflow;
   1.125 +    const int bh = 8 * num_8x8_blocks_high_lookup[bs] - bottom_overflow;
   1.126 +    int avg;
   1.127 +    variance(x->plane[0].src.buf, x->plane[0].src.stride,
   1.128 +             vp9_64_zeros, 0, bw, bh, &sse, &avg);
   1.129 +    var = sse - (((int64_t)avg * avg) / (bw * bh));
   1.130 +    return (256 * var) / (bw * bh);
   1.131 +  } else {
   1.132 +    var = cpi->fn_ptr[bs].vf(x->plane[0].src.buf,
   1.133 +                             x->plane[0].src.stride,
   1.134 +                             vp9_64_zeros, 0, &sse);
   1.135 +    return (256 * var) >> num_pels_log2_lookup[bs];
   1.136 +  }
   1.137 +}
   1.138 +
   1.139 +int vp9_block_energy(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs) {
   1.140 +  double energy;
   1.141 +  unsigned int var = block_variance(cpi, x, bs);
   1.142 +
   1.143 +  vp9_clear_system_state();  // __asm emms;
   1.144 +
   1.145 +  // if (var <= 1000)
   1.146 +  //   return 0;
   1.147 +
   1.148 +  energy = 0.9*(logf(var + 1) - 10.0);
   1.149 +  return clamp(round(energy), ENERGY_MIN, ENERGY_MAX);
   1.150 +}

mercurial