pickcdef.c 17.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
 *
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
 */

#include <math.h>
#include <string.h>

#include "./aom_scale_rtcd.h"
#include "aom/aom_integer.h"
#include "av1/common/cdef.h"
#include "av1/common/onyxc_int.h"
#include "av1/common/reconinter.h"
#include "av1/encoder/encoder.h"

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#define TOTAL_STRENGTHS (DERING_STRENGTHS * CLPF_STRENGTHS)

/* Search for the best strength to add as an option, knowing we
   already selected nb_strengths options. */
static uint64_t search_one(int *lev, int nb_strengths,
                           uint64_t mse[][TOTAL_STRENGTHS], int sb_count) {
  uint64_t tot_mse[TOTAL_STRENGTHS];
  int i, j;
  uint64_t best_tot_mse = (uint64_t)1 << 63;
  int best_id = 0;
  memset(tot_mse, 0, sizeof(tot_mse));
  for (i = 0; i < sb_count; i++) {
    int gi;
    uint64_t best_mse = (uint64_t)1 << 63;
    /* Find best mse among already selected options. */
    for (gi = 0; gi < nb_strengths; gi++) {
      if (mse[i][lev[gi]] < best_mse) {
        best_mse = mse[i][lev[gi]];
      }
    }
    /* Find best mse when adding each possible new option. */
    for (j = 0; j < TOTAL_STRENGTHS; j++) {
      uint64_t best = best_mse;
      if (mse[i][j] < best) best = mse[i][j];
      tot_mse[j] += best;
    }
  }
  for (j = 0; j < TOTAL_STRENGTHS; j++) {
    if (tot_mse[j] < best_tot_mse) {
      best_tot_mse = tot_mse[j];
      best_id = j;
    }
  }
  lev[nb_strengths] = best_id;
  return best_tot_mse;
}

Jean-Marc Valin's avatar
Jean-Marc Valin committed
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/* Search for the best luma+chroma strength to add as an option, knowing we
   already selected nb_strengths options. */
static uint64_t search_one_dual(int *lev0, int *lev1, int nb_strengths,
                                uint64_t (**mse)[TOTAL_STRENGTHS],
                                int sb_count) {
  uint64_t tot_mse[TOTAL_STRENGTHS][TOTAL_STRENGTHS];
  int i, j;
  uint64_t best_tot_mse = (uint64_t)1 << 63;
  int best_id0 = 0;
  int best_id1 = 0;
  memset(tot_mse, 0, sizeof(tot_mse));
  for (i = 0; i < sb_count; i++) {
    int gi;
    uint64_t best_mse = (uint64_t)1 << 63;
    /* Find best mse among already selected options. */
    for (gi = 0; gi < nb_strengths; gi++) {
      uint64_t curr = mse[0][i][lev0[gi]];
      curr += mse[1][i][lev1[gi]];
      if (curr < best_mse) {
        best_mse = curr;
      }
    }
    /* Find best mse when adding each possible new option. */
    for (j = 0; j < TOTAL_STRENGTHS; j++) {
      int k;
      for (k = 0; k < TOTAL_STRENGTHS; k++) {
        uint64_t best = best_mse;
        uint64_t curr = mse[0][i][j];
        curr += mse[1][i][k];
        if (curr < best) best = curr;
        tot_mse[j][k] += best;
      }
    }
  }
  for (j = 0; j < TOTAL_STRENGTHS; j++) {
    int k;
    for (k = 0; k < TOTAL_STRENGTHS; k++) {
      if (tot_mse[j][k] < best_tot_mse) {
        best_tot_mse = tot_mse[j][k];
        best_id0 = j;
        best_id1 = k;
      }
    }
  }
  lev0[nb_strengths] = best_id0;
  lev1[nb_strengths] = best_id1;
  return best_tot_mse;
}

108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/* Search for the set of strengths that minimizes mse. */
static uint64_t joint_strength_search(int *best_lev, int nb_strengths,
                                      uint64_t mse[][TOTAL_STRENGTHS],
                                      int sb_count) {
  uint64_t best_tot_mse;
  int i;
  best_tot_mse = (uint64_t)1 << 63;
  /* Greedy search: add one strength options at a time. */
  for (i = 0; i < nb_strengths; i++) {
    best_tot_mse = search_one(best_lev, i, mse, sb_count);
  }
  /* Trying to refine the greedy search by reconsidering each
     already-selected option. */
  for (i = 0; i < 4 * nb_strengths; i++) {
    int j;
    for (j = 0; j < nb_strengths - 1; j++) best_lev[j] = best_lev[j + 1];
    best_tot_mse = search_one(best_lev, nb_strengths - 1, mse, sb_count);
  }
  return best_tot_mse;
}

Jean-Marc Valin's avatar
Jean-Marc Valin committed
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/* Search for the set of luma+chroma strengths that minimizes mse. */
static uint64_t joint_strength_search_dual(int *best_lev0, int *best_lev1,
                                           int nb_strengths,
                                           uint64_t (**mse)[TOTAL_STRENGTHS],
                                           int sb_count) {
  uint64_t best_tot_mse;
  int i;
  best_tot_mse = (uint64_t)1 << 63;
  /* Greedy search: add one strength options at a time. */
  for (i = 0; i < nb_strengths; i++) {
    best_tot_mse = search_one_dual(best_lev0, best_lev1, i, mse, sb_count);
  }
  /* Trying to refine the greedy search by reconsidering each
     already-selected option. */
  for (i = 0; i < 4 * nb_strengths; i++) {
    int j;
    for (j = 0; j < nb_strengths - 1; j++) {
      best_lev0[j] = best_lev0[j + 1];
      best_lev1[j] = best_lev1[j + 1];
    }
    best_tot_mse =
        search_one_dual(best_lev0, best_lev1, nb_strengths - 1, mse, sb_count);
  }
  return best_tot_mse;
}

155
156
157
158
159
160
161
162
163
164
165
166
167
/* FIXME: SSE-optimize this. */
static void copy_sb16_16(uint16_t *dst, int dstride, const uint16_t *src,
                         int src_voffset, int src_hoffset, int sstride,
                         int vsize, int hsize) {
  int r, c;
  const uint16_t *base = &src[src_voffset * sstride + src_hoffset];
  for (r = 0; r < vsize; r++) {
    for (c = 0; c < hsize; c++) {
      dst[r * dstride + c] = base[r * sstride + c];
    }
  }
}

168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
static INLINE uint64_t dist_8x8_16bit(uint16_t *dst, int dstride, uint16_t *src,
                                      int sstride, int coeff_shift) {
  uint64_t svar = 0;
  uint64_t dvar = 0;
  uint64_t sum_s = 0;
  uint64_t sum_d = 0;
  uint64_t sum_s2 = 0;
  uint64_t sum_d2 = 0;
  uint64_t sum_sd = 0;
  int i, j;
  for (i = 0; i < 8; i++) {
    for (j = 0; j < 8; j++) {
      sum_s += src[i * sstride + j];
      sum_d += dst[i * dstride + j];
      sum_s2 += src[i * sstride + j] * src[i * sstride + j];
      sum_d2 += dst[i * dstride + j] * dst[i * dstride + j];
      sum_sd += src[i * sstride + j] * dst[i * dstride + j];
    }
  }
  /* Compute the variance -- the calculation cannot go negative. */
  svar = sum_s2 - ((sum_s * sum_s + 32) >> 6);
  dvar = sum_d2 - ((sum_d * sum_d + 32) >> 6);
  return (uint64_t)floor(
      .5 +
      (sum_d2 + sum_s2 - 2 * sum_sd) * .5 *
          (svar + dvar + (400 << 2 * coeff_shift)) /
          (sqrt((20000 << 4 * coeff_shift) + svar * (double)dvar)));
}

197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
static INLINE uint64_t mse_8x8_16bit(uint16_t *dst, int dstride, uint16_t *src,
                                     int sstride) {
  uint64_t sum = 0;
  int i, j;
  for (i = 0; i < 8; i++) {
    for (j = 0; j < 8; j++) {
      int e = dst[i * dstride + j] - src[i * sstride + j];
      sum += e * e;
    }
  }
  return sum;
}

static INLINE uint64_t mse_4x4_16bit(uint16_t *dst, int dstride, uint16_t *src,
                                     int sstride) {
  uint64_t sum = 0;
  int i, j;
  for (i = 0; i < 4; i++) {
    for (j = 0; j < 4; j++) {
      int e = dst[i * dstride + j] - src[i * sstride + j];
      sum += e * e;
    }
  }
  return sum;
}

/* Compute MSE only on the blocks we filtered. */
224
225
226
uint64_t compute_dering_dist(uint16_t *dst, int dstride, uint16_t *src,
                             dering_list *dlist, int dering_count,
                             BLOCK_SIZE bsize, int coeff_shift, int pli) {
227
228
  uint64_t sum = 0;
  int bi, bx, by;
229
  if (bsize == BLOCK_8X8) {
230
231
232
    for (bi = 0; bi < dering_count; bi++) {
      by = dlist[bi].by;
      bx = dlist[bi].bx;
233
234
      if (pli == 0) {
        sum += dist_8x8_16bit(&dst[(by << 3) * dstride + (bx << 3)], dstride,
235
                              &src[bi << (3 + 3)], 8, coeff_shift);
236
237
      } else {
        sum += mse_8x8_16bit(&dst[(by << 3) * dstride + (bx << 3)], dstride,
238
                             &src[bi << (3 + 3)], 8);
239
      }
240
    }
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
  } else if (bsize == BLOCK_4X8) {
    for (bi = 0; bi < dering_count; bi++) {
      by = dlist[bi].by;
      bx = dlist[bi].bx;
      sum += mse_4x4_16bit(&dst[(by << 3) * dstride + (bx << 2)], dstride,
                           &src[bi << (3 + 2)], 4);
      sum += mse_4x4_16bit(&dst[((by << 3) + 4) * dstride + (bx << 2)], dstride,
                           &src[(bi << (3 + 2)) + 4 * 4], 4);
    }
  } else if (bsize == BLOCK_8X4) {
    for (bi = 0; bi < dering_count; bi++) {
      by = dlist[bi].by;
      bx = dlist[bi].bx;
      sum += mse_4x4_16bit(&dst[(by << 2) * dstride + (bx << 3)], dstride,
                           &src[bi << (2 + 3)], 8);
      sum += mse_4x4_16bit(&dst[(by << 2) * dstride + (bx << 3) + 4], dstride,
                           &src[(bi << (2 + 3)) + 4], 8);
    }
259
  } else {
260
    assert(bsize == BLOCK_4X4);
261
262
263
264
    for (bi = 0; bi < dering_count; bi++) {
      by = dlist[bi].by;
      bx = dlist[bi].bx;
      sum += mse_4x4_16bit(&dst[(by << 2) * dstride + (bx << 2)], dstride,
265
                           &src[bi << (2 + 2)], 4);
266
267
268
269
270
    }
  }
  return sum >> 2 * coeff_shift;
}

271
272
273
274
void av1_cdef_search(YV12_BUFFER_CONFIG *frame, const YV12_BUFFER_CONFIG *ref,
                     AV1_COMMON *cm, MACROBLOCKD *xd) {
  int r, c;
  int sbr, sbc;
275
276
  uint16_t *src[3];
  uint16_t *ref_coeff[3];
277
278
  dering_list dlist[MAX_MIB_SIZE * MAX_MIB_SIZE];
  int dir[OD_DERING_NBLOCKS][OD_DERING_NBLOCKS] = { { 0 } };
279
  int var[OD_DERING_NBLOCKS][OD_DERING_NBLOCKS] = { { 0 } };
280
  int stride[3];
281
  int bsize[3];
282
283
  int mi_wide_l2[3];
  int mi_high_l2[3];
284
285
  int xdec[3];
  int ydec[3];
286
287
288
  int pli;
  int dering_count;
  int coeff_shift = AOMMAX(cm->bit_depth - 8, 0);
289
290
  uint64_t best_tot_mse = (uint64_t)1 << 63;
  uint64_t tot_mse;
291
292
293
294
  int sb_count;
  int nvsb = (cm->mi_rows + MAX_MIB_SIZE - 1) / MAX_MIB_SIZE;
  int nhsb = (cm->mi_cols + MAX_MIB_SIZE - 1) / MAX_MIB_SIZE;
  int *sb_index = aom_malloc(nvsb * nhsb * sizeof(*sb_index));
295
  int *selected_strength = aom_malloc(nvsb * nhsb * sizeof(*sb_index));
Jean-Marc Valin's avatar
Jean-Marc Valin committed
296
  uint64_t(*mse[2])[TOTAL_STRENGTHS];
297
298
  int clpf_damping = 3 + (cm->base_qindex >> 6);
  int i;
299
300
301
302
  int nb_strengths;
  int nb_strength_bits;
  int quantizer;
  double lambda;
303
  int nplanes = 3;
304
305
  DECLARE_ALIGNED(32, uint16_t, inbuf[OD_DERING_INBUF_SIZE]);
  uint16_t *in;
306
  DECLARE_ALIGNED(32, uint16_t, tmp_dst[MAX_SB_SQUARE]);
307
308
309
  int chroma_dering =
      xd->plane[1].subsampling_x == xd->plane[1].subsampling_y &&
      xd->plane[2].subsampling_x == xd->plane[2].subsampling_y;
310
311
312
  quantizer =
      av1_ac_quant(cm->base_qindex, 0, cm->bit_depth) >> (cm->bit_depth - 8);
  lambda = .12 * quantizer * quantizer / 256.;
313
314

  av1_setup_dst_planes(xd->plane, frame, 0, 0);
Jean-Marc Valin's avatar
Jean-Marc Valin committed
315
316
  mse[0] = aom_malloc(sizeof(**mse) * nvsb * nhsb);
  mse[1] = aom_malloc(sizeof(**mse) * nvsb * nhsb);
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
  for (pli = 0; pli < nplanes; pli++) {
    uint8_t *ref_buffer;
    int ref_stride;
    switch (pli) {
      case 0:
        ref_buffer = ref->y_buffer;
        ref_stride = ref->y_stride;
        break;
      case 1:
        ref_buffer = ref->u_buffer;
        ref_stride = ref->uv_stride;
        break;
      case 2:
        ref_buffer = ref->v_buffer;
        ref_stride = ref->uv_stride;
        break;
    }
334
335
336
337
    src[pli] = aom_memalign(
        32, sizeof(*src) * cm->mi_rows * cm->mi_cols * MI_SIZE * MI_SIZE);
    ref_coeff[pli] = aom_memalign(
        32, sizeof(*ref_coeff) * cm->mi_rows * cm->mi_cols * MI_SIZE * MI_SIZE);
338
339
340
341
    xdec[pli] = xd->plane[pli].subsampling_x;
    ydec[pli] = xd->plane[pli].subsampling_y;
    bsize[pli] = ydec[pli] ? (xdec[pli] ? BLOCK_4X4 : BLOCK_8X4)
                           : (xdec[pli] ? BLOCK_4X8 : BLOCK_8X8);
342
    stride[pli] = cm->mi_cols << MI_SIZE_LOG2;
343
344
    mi_wide_l2[pli] = MI_SIZE_LOG2 - xd->plane[pli].subsampling_x;
    mi_high_l2[pli] = MI_SIZE_LOG2 - xd->plane[pli].subsampling_y;
345
346
347
348
349
350
351
352

    const int frame_height =
        (cm->mi_rows * MI_SIZE) >> xd->plane[pli].subsampling_y;
    const int frame_width =
        (cm->mi_cols * MI_SIZE) >> xd->plane[pli].subsampling_x;

    for (r = 0; r < frame_height; ++r) {
      for (c = 0; c < frame_width; ++c) {
353
#if CONFIG_AOM_HIGHBITDEPTH
354
355
356
357
358
359
        if (cm->use_highbitdepth) {
          src[pli][r * stride[pli] + c] = CONVERT_TO_SHORTPTR(
              xd->plane[pli].dst.buf)[r * xd->plane[pli].dst.stride + c];
          ref_coeff[pli][r * stride[pli] + c] =
              CONVERT_TO_SHORTPTR(ref_buffer)[r * ref_stride + c];
        } else {
360
#endif
361
362
363
          src[pli][r * stride[pli] + c] =
              xd->plane[pli].dst.buf[r * xd->plane[pli].dst.stride + c];
          ref_coeff[pli][r * stride[pli] + c] = ref_buffer[r * ref_stride + c];
364
#if CONFIG_AOM_HIGHBITDEPTH
365
        }
366
#endif
367
      }
368
369
    }
  }
370
  in = inbuf + OD_FILT_VBORDER * OD_FILT_BSTRIDE + OD_FILT_HBORDER;
371
  sb_count = 0;
372
373
  for (sbr = 0; sbr < nvsb; ++sbr) {
    for (sbc = 0; sbc < nhsb; ++sbc) {
374
375
      int nvb, nhb;
      int gi;
376
      int dirinit = 0;
377
378
379
380
      nhb = AOMMIN(MAX_MIB_SIZE, cm->mi_cols - MAX_MIB_SIZE * sbc);
      nvb = AOMMIN(MAX_MIB_SIZE, cm->mi_rows - MAX_MIB_SIZE * sbr);
      dering_count = sb_compute_dering_list(cm, sbr * MAX_MIB_SIZE,
                                            sbc * MAX_MIB_SIZE, dlist);
381
382
383
      cm->mi_grid_visible[MAX_MIB_SIZE * sbr * cm->mi_stride +
                          MAX_MIB_SIZE * sbc]
          ->mbmi.cdef_strength = -1;
384
      if (dering_count == 0) continue;
385
      for (pli = 0; pli < nplanes; pli++) {
386
387
388
389
        for (i = 0; i < OD_DERING_INBUF_SIZE; i++)
          inbuf[i] = OD_DERING_VERY_LARGE;
        for (gi = 0; gi < TOTAL_STRENGTHS; gi++) {
          int threshold;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
390
          uint64_t curr_mse;
391
          int clpf_strength;
392
          threshold = gi / CLPF_STRENGTHS;
393
394
395
396
397
          if (pli > 0 && !chroma_dering) threshold = 0;
          /* We avoid filtering the pixels for which some of the pixels to
             average
             are outside the frame. We could change the filter instead, but it
             would add special cases for any future vectorization. */
398
399
          int yoff = OD_FILT_VBORDER * (sbr != 0);
          int xoff = OD_FILT_HBORDER * (sbc != 0);
400
401
402
403
          int ysize = (nvb << mi_high_l2[pli]) +
                      OD_FILT_VBORDER * (sbr != nvsb - 1) + yoff;
          int xsize = (nhb << mi_wide_l2[pli]) +
                      OD_FILT_HBORDER * (sbc != nhsb - 1) + xoff;
404
          clpf_strength = gi % CLPF_STRENGTHS;
405
406
          if (clpf_strength == 0)
            copy_sb16_16(&in[(-yoff * OD_FILT_BSTRIDE - xoff)], OD_FILT_BSTRIDE,
407
408
409
410
                         src[pli],
                         (sbr * MAX_MIB_SIZE << mi_high_l2[pli]) - yoff,
                         (sbc * MAX_MIB_SIZE << mi_wide_l2[pli]) - xoff,
                         stride[pli], ysize, xsize);
411
          od_dering(clpf_strength ? NULL : (uint8_t *)in, OD_FILT_BSTRIDE,
412
413
                    tmp_dst, in, xdec[pli], ydec[pli], dir, &dirinit, var, pli,
                    dlist, dering_count, threshold,
414
                    clpf_strength + (clpf_strength == 3), clpf_damping,
415
                    coeff_shift, clpf_strength != 0, 1);
Jean-Marc Valin's avatar
Jean-Marc Valin committed
416
          curr_mse = compute_dering_dist(
417
              ref_coeff[pli] +
418
419
                  (sbr * MAX_MIB_SIZE << mi_high_l2[pli]) * stride[pli] +
                  (sbc * MAX_MIB_SIZE << mi_wide_l2[pli]),
420
              stride[pli], tmp_dst, dlist, dering_count, bsize[pli],
421
              coeff_shift, pli);
Jean-Marc Valin's avatar
Jean-Marc Valin committed
422
423
424
425
          if (pli < 2)
            mse[pli][sb_count][gi] = curr_mse;
          else
            mse[1][sb_count][gi] += curr_mse;
426
427
          sb_index[sb_count] =
              MAX_MIB_SIZE * sbr * cm->mi_stride + MAX_MIB_SIZE * sbc;
428
429
430
431
432
        }
      }
      sb_count++;
    }
  }
433
434
435
  nb_strength_bits = 0;
  /* Search for different number of signalling bits. */
  for (i = 0; i <= 3; i++) {
Jean-Marc Valin's avatar
Jean-Marc Valin committed
436
    int j;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
437
438
    int best_lev0[CDEF_MAX_STRENGTHS];
    int best_lev1[CDEF_MAX_STRENGTHS] = { 0 };
439
    nb_strengths = 1 << i;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
440
441
442
443
444
445
    if (nplanes >= 3)
      tot_mse = joint_strength_search_dual(best_lev0, best_lev1, nb_strengths,
                                           mse, sb_count);
    else
      tot_mse =
          joint_strength_search(best_lev0, nb_strengths, mse[0], sb_count);
446
447
448
449
450
451
452
    /* Count superblock signalling cost. */
    tot_mse += (uint64_t)(sb_count * lambda * i);
    /* Count header signalling cost. */
    tot_mse += (uint64_t)(nb_strengths * lambda * CDEF_STRENGTH_BITS);
    if (tot_mse < best_tot_mse) {
      best_tot_mse = tot_mse;
      nb_strength_bits = i;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
453
      for (j = 0; j < 1 << nb_strength_bits; j++) {
Jean-Marc Valin's avatar
Jean-Marc Valin committed
454
455
        cm->cdef_strengths[j] = best_lev0[j];
        cm->cdef_uv_strengths[j] = best_lev1[j];
Jean-Marc Valin's avatar
Jean-Marc Valin committed
456
      }
457
458
    }
  }
459
  nb_strengths = 1 << nb_strength_bits;
460

461
462
  cm->cdef_bits = nb_strength_bits;
  cm->nb_cdef_strengths = nb_strengths;
463
  for (i = 0; i < sb_count; i++) {
464
465
    int gi;
    int best_gi;
466
    uint64_t best_mse = (uint64_t)1 << 63;
467
468
    best_gi = 0;
    for (gi = 0; gi < cm->nb_cdef_strengths; gi++) {
Jean-Marc Valin's avatar
Jean-Marc Valin committed
469
470
471
      uint64_t curr = mse[0][i][cm->cdef_strengths[gi]];
      if (nplanes >= 3) curr += mse[1][i][cm->cdef_uv_strengths[gi]];
      if (curr < best_mse) {
472
        best_gi = gi;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
473
        best_mse = curr;
474
475
      }
    }
476
    selected_strength[i] = best_gi;
477
    cm->mi_grid_visible[sb_index[i]]->mbmi.cdef_strength = best_gi;
478
  }
Jean-Marc Valin's avatar
Jean-Marc Valin committed
479
480
  aom_free(mse[0]);
  aom_free(mse[1]);
481
482
483
484
  for (pli = 0; pli < nplanes; pli++) {
    aom_free(src[pli]);
    aom_free(ref_coeff[pli]);
  }
485
  aom_free(sb_index);
486
  aom_free(selected_strength);
487
}