blob: 77fbaac78e580a9fb77c68770a27cb7fd75f23bf [file] [log] [blame]
Yaowu Xuc27fc142016-08-22 16:08:15 -07001/*
2 * Copyright (c) 2015 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 <string.h>
12
Yaowu Xuf883b422016-08-30 14:01:10 -070013#include "./aom_scale_rtcd.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070014#include "av1/common/dering.h"
15#include "av1/common/onyxc_int.h"
16#include "av1/common/reconinter.h"
17#include "av1/encoder/encoder.h"
Yaowu Xuf883b422016-08-30 14:01:10 -070018#include "aom/aom_integer.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070019
20static double compute_dist(int16_t *x, int xstride, int16_t *y, int ystride,
21 int nhb, int nvb, int coeff_shift) {
22 int i, j;
23 double sum;
24 sum = 0;
25 for (i = 0; i < nvb << 3; i++) {
26 for (j = 0; j < nhb << 3; j++) {
27 double tmp;
28 tmp = x[i * xstride + j] - y[i * ystride + j];
29 sum += tmp * tmp;
30 }
31 }
32 return sum / (double)(1 << 2 * coeff_shift);
33}
34
Yaowu Xuf883b422016-08-30 14:01:10 -070035int av1_dering_search(YV12_BUFFER_CONFIG *frame, const YV12_BUFFER_CONFIG *ref,
36 AV1_COMMON *cm, MACROBLOCKD *xd) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070037 int r, c;
38 int sbr, sbc;
39 int nhsb, nvsb;
40 od_dering_in *src;
41 int16_t *ref_coeff;
42 unsigned char *bskip;
43 int dir[OD_DERING_NBLOCKS][OD_DERING_NBLOCKS] = { { 0 } };
44 int stride;
45 int bsize[3];
46 int dec[3];
47 int pli;
48 int(*mse)[MAX_DERING_LEVEL];
Yaowu Xuc27fc142016-08-22 16:08:15 -070049 double tot_mse[MAX_DERING_LEVEL] = { 0 };
50 int level;
51 int best_level;
52 int global_level;
53 double best_tot_mse = 1e15;
Yaowu Xuf883b422016-08-30 14:01:10 -070054 int coeff_shift = AOMMAX(cm->bit_depth - 8, 0);
55 src = aom_malloc(sizeof(*src) * cm->mi_rows * cm->mi_cols * 64);
56 ref_coeff = aom_malloc(sizeof(*ref_coeff) * cm->mi_rows * cm->mi_cols * 64);
57 bskip = aom_malloc(sizeof(*bskip) * cm->mi_rows * cm->mi_cols);
58 av1_setup_dst_planes(xd->plane, frame, 0, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -070059 for (pli = 0; pli < 3; pli++) {
60 dec[pli] = xd->plane[pli].subsampling_x;
61 bsize[pli] = 8 >> dec[pli];
62 }
63 stride = bsize[0] * cm->mi_cols;
64 for (r = 0; r < bsize[0] * cm->mi_rows; ++r) {
65 for (c = 0; c < bsize[0] * cm->mi_cols; ++c) {
Yaowu Xuf883b422016-08-30 14:01:10 -070066#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070067 if (cm->use_highbitdepth) {
68 src[r * stride + c] = CONVERT_TO_SHORTPTR(
69 xd->plane[0].dst.buf)[r * xd->plane[0].dst.stride + c];
70 ref_coeff[r * stride + c] =
71 CONVERT_TO_SHORTPTR(ref->y_buffer)[r * ref->y_stride + c];
72 } else {
73#endif
74 src[r * stride + c] =
75 xd->plane[0].dst.buf[r * xd->plane[0].dst.stride + c];
76 ref_coeff[r * stride + c] = ref->y_buffer[r * ref->y_stride + c];
Yaowu Xuf883b422016-08-30 14:01:10 -070077#if CONFIG_AOM_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070078 }
79#endif
80 }
81 }
82 for (r = 0; r < cm->mi_rows; ++r) {
83 for (c = 0; c < cm->mi_cols; ++c) {
84 const MB_MODE_INFO *mbmi =
85 &cm->mi_grid_visible[r * cm->mi_stride + c]->mbmi;
86 bskip[r * cm->mi_cols + c] = mbmi->skip;
87 }
88 }
89 nvsb = (cm->mi_rows + MAX_MIB_SIZE - 1) / MAX_MIB_SIZE;
90 nhsb = (cm->mi_cols + MAX_MIB_SIZE - 1) / MAX_MIB_SIZE;
Yaowu Xuf883b422016-08-30 14:01:10 -070091 mse = aom_malloc(nvsb * nhsb * sizeof(*mse));
Yaowu Xuc27fc142016-08-22 16:08:15 -070092 for (sbr = 0; sbr < nvsb; sbr++) {
93 for (sbc = 0; sbc < nhsb; sbc++) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070094 int nvb, nhb;
95 int16_t dst[MAX_MIB_SIZE * MAX_MIB_SIZE * 8 * 8];
Yaowu Xuf883b422016-08-30 14:01:10 -070096 nhb = AOMMIN(MAX_MIB_SIZE, cm->mi_cols - MAX_MIB_SIZE * sbc);
97 nvb = AOMMIN(MAX_MIB_SIZE, cm->mi_rows - MAX_MIB_SIZE * sbr);
Yaowu Xuc27fc142016-08-22 16:08:15 -070098 for (level = 0; level < 64; level++) {
Yaowu Xu9c323bc2016-09-01 11:35:16 -070099 int cur_mse;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700100 int threshold;
101 threshold = level << coeff_shift;
102 od_dering(
103 &OD_DERING_VTBL_C, dst, MAX_MIB_SIZE * bsize[0],
104 &src[sbr * stride * bsize[0] * MAX_MIB_SIZE +
105 sbc * bsize[0] * MAX_MIB_SIZE],
106 cm->mi_cols * bsize[0], nhb, nvb, sbc, sbr, nhsb, nvsb, 0, dir, 0,
107 &bskip[MAX_MIB_SIZE * sbr * cm->mi_cols + MAX_MIB_SIZE * sbc],
108 cm->mi_cols, threshold, OD_DERING_NO_CHECK_OVERLAP, coeff_shift);
Yaowu Xu9c323bc2016-09-01 11:35:16 -0700109 cur_mse = (int)compute_dist(
Yaowu Xuc27fc142016-08-22 16:08:15 -0700110 dst, MAX_MIB_SIZE * bsize[0],
111 &ref_coeff[sbr * stride * bsize[0] * MAX_MIB_SIZE +
112 sbc * bsize[0] * MAX_MIB_SIZE],
113 stride, nhb, nvb, coeff_shift);
Yaowu Xu9c323bc2016-09-01 11:35:16 -0700114 mse[nhsb * sbr + sbc][level] = cur_mse;
115 tot_mse[level] += cur_mse;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700116 }
Yaowu Xuc27fc142016-08-22 16:08:15 -0700117 }
118 }
119#if DERING_REFINEMENT
120 best_level = 0;
121 /* Search for the best global level one value at a time. */
122 for (global_level = 2; global_level < MAX_DERING_LEVEL; global_level++) {
123 double tot_mse = 0;
124 for (sbr = 0; sbr < nvsb; sbr++) {
125 for (sbc = 0; sbc < nhsb; sbc++) {
126 int gi;
127 int best_mse = mse[nhsb * sbr + sbc][0];
128 for (gi = 1; gi < 4; gi++) {
129 level = compute_level_from_index(global_level, gi);
130 if (mse[nhsb * sbr + sbc][level] < best_mse) {
131 best_mse = mse[nhsb * sbr + sbc][level];
132 }
133 }
134 tot_mse += best_mse;
135 }
136 }
137 if (tot_mse < best_tot_mse) {
138 best_level = global_level;
139 best_tot_mse = tot_mse;
140 }
141 }
142 for (sbr = 0; sbr < nvsb; sbr++) {
143 for (sbc = 0; sbc < nhsb; sbc++) {
144 int gi;
145 int best_gi;
146 int best_mse = mse[nhsb * sbr + sbc][0];
147 best_gi = 0;
148 for (gi = 1; gi < DERING_REFINEMENT_LEVELS; gi++) {
149 level = compute_level_from_index(best_level, gi);
150 if (mse[nhsb * sbr + sbc][level] < best_mse) {
151 best_gi = gi;
152 best_mse = mse[nhsb * sbr + sbc][level];
153 }
154 }
155 cm->mi_grid_visible[MAX_MIB_SIZE * sbr * cm->mi_stride +
156 MAX_MIB_SIZE * sbc]
157 ->mbmi.dering_gain = best_gi;
158 }
159 }
160#else
161 best_level = 0;
162 for (level = 0; level < MAX_DERING_LEVEL; level++) {
163 if (tot_mse[level] < tot_mse[best_level]) best_level = level;
164 }
165#endif
Yaowu Xuf883b422016-08-30 14:01:10 -0700166 aom_free(src);
167 aom_free(ref_coeff);
168 aom_free(bskip);
169 aom_free(mse);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700170 return best_level;
171}