480 строки
18 KiB
C
480 строки
18 KiB
C
/*
|
|
* Copyright (c) 2016 The WebM project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include <math.h>
|
|
|
|
#include "./vpx_config.h"
|
|
#include "./vpx_dsp_rtcd.h"
|
|
#include "vp10/common/onyxc_int.h"
|
|
#include "vp10/common/restoration.h"
|
|
#include "vpx_dsp/vpx_dsp_common.h"
|
|
#include "vpx_mem/vpx_mem.h"
|
|
#include "vpx_ports/mem.h"
|
|
|
|
#define RESTORATION_PARAM_PRECISION 16
|
|
#define RESTORATION_RANGE 256
|
|
#define RESTORATION_RANGE_SYM (2 * RESTORATION_RANGE + 1)
|
|
|
|
static uint8_t restoration_filters_r_kf[RESTORATION_LEVELS_KF]
|
|
[RESTORATION_RANGE_SYM];
|
|
static uint8_t restoration_filters_r[RESTORATION_LEVELS]
|
|
[RESTORATION_RANGE_SYM];
|
|
static uint8_t restoration_filters_s_kf[RESTORATION_LEVELS_KF]
|
|
[RESTORATION_WIN][RESTORATION_WIN];
|
|
static uint8_t restoration_filters_s[RESTORATION_LEVELS]
|
|
[RESTORATION_WIN][RESTORATION_WIN];
|
|
|
|
typedef struct restoration_params {
|
|
int sigma_x; // spatial variance x
|
|
int sigma_y; // spatial variance y
|
|
int sigma_r; // range variance
|
|
} RestorationParamsType;
|
|
|
|
static RestorationParamsType
|
|
restoration_level_to_params_arr[RESTORATION_LEVELS] = {
|
|
// Values are rounded to 1/16 th precision
|
|
{8, 9, 30},
|
|
{9, 8, 30},
|
|
{9, 11, 32},
|
|
{11, 9, 32},
|
|
{14, 14, 32},
|
|
{18, 18, 36},
|
|
{24, 24, 40},
|
|
{32, 32, 40},
|
|
};
|
|
|
|
static RestorationParamsType
|
|
restoration_level_to_params_arr_kf[RESTORATION_LEVELS_KF] = {
|
|
// Values are rounded to 1/16 th precision
|
|
{8, 8, 30},
|
|
{9, 9, 32},
|
|
{10, 10, 32},
|
|
{12, 12, 32},
|
|
{14, 14, 32},
|
|
{18, 18, 36},
|
|
{24, 24, 40},
|
|
{30, 30, 44},
|
|
{36, 36, 48},
|
|
{42, 42, 48},
|
|
{48, 48, 48},
|
|
{48, 48, 56},
|
|
{56, 56, 48},
|
|
{56, 56, 56},
|
|
{56, 56, 64},
|
|
{64, 64, 48},
|
|
};
|
|
|
|
typedef void (*restore_func_type)(
|
|
uint8_t *data8, int width, int height,
|
|
int stride, RestorationInternal *rst,
|
|
uint8_t *tmpdata8, int tmpstride);
|
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
typedef void (*restore_func_highbd_type)(
|
|
uint8_t *data8, int width, int height,
|
|
int stride, RestorationInternal *rst,
|
|
uint8_t *tmpdata8, int tmpstride,
|
|
int bit_depth);
|
|
#endif // CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
static INLINE RestorationParamsType vp10_restoration_level_to_params(
|
|
int index, int kf) {
|
|
return kf ? restoration_level_to_params_arr_kf[index] :
|
|
restoration_level_to_params_arr[index];
|
|
}
|
|
|
|
void vp10_loop_restoration_precal() {
|
|
int i;
|
|
for (i = 0; i < RESTORATION_LEVELS_KF; i ++) {
|
|
const RestorationParamsType param = vp10_restoration_level_to_params(i, 1);
|
|
const int sigma_x = param.sigma_x;
|
|
const int sigma_y = param.sigma_y;
|
|
const int sigma_r = param.sigma_r;
|
|
const double sigma_r_d = (double)sigma_r / RESTORATION_PARAM_PRECISION;
|
|
const double sigma_x_d = (double)sigma_x / RESTORATION_PARAM_PRECISION;
|
|
const double sigma_y_d = (double)sigma_y / RESTORATION_PARAM_PRECISION;
|
|
|
|
uint8_t *fr = restoration_filters_r_kf[i] + RESTORATION_RANGE;
|
|
int j, x, y;
|
|
for (j = 0; j <= RESTORATION_RANGE; j++) {
|
|
fr[j] = (uint8_t)(0.5 + RESTORATION_FILT_STEP *
|
|
exp(-(j * j) / (2 * sigma_r_d * sigma_r_d)));
|
|
fr[-j] = fr[j];
|
|
}
|
|
for (y = -RESTORATION_HALFWIN; y <= RESTORATION_HALFWIN; y++) {
|
|
for (x = -RESTORATION_HALFWIN; x <= RESTORATION_HALFWIN; x++) {
|
|
restoration_filters_s_kf[i][y + RESTORATION_HALFWIN]
|
|
[x + RESTORATION_HALFWIN] =
|
|
(uint8_t)(0.5 + RESTORATION_FILT_STEP *
|
|
exp(-(x * x) / (2 * sigma_x_d * sigma_x_d)
|
|
-(y * y) / (2 * sigma_y_d * sigma_y_d)));
|
|
}
|
|
}
|
|
}
|
|
for (i = 0; i < RESTORATION_LEVELS; i ++) {
|
|
const RestorationParamsType param = vp10_restoration_level_to_params(i, 0);
|
|
const int sigma_x = param.sigma_x;
|
|
const int sigma_y = param.sigma_y;
|
|
const int sigma_r = param.sigma_r;
|
|
const double sigma_r_d = (double)sigma_r / RESTORATION_PARAM_PRECISION;
|
|
const double sigma_x_d = (double)sigma_x / RESTORATION_PARAM_PRECISION;
|
|
const double sigma_y_d = (double)sigma_y / RESTORATION_PARAM_PRECISION;
|
|
|
|
uint8_t *fr = restoration_filters_r[i] + RESTORATION_RANGE;
|
|
int j, x, y;
|
|
for (j = 0; j <= RESTORATION_RANGE; j++) {
|
|
fr[j] = (uint8_t)(0.5 + RESTORATION_FILT_STEP *
|
|
exp(-(j * j) / (2 * sigma_r_d * sigma_r_d)));
|
|
fr[-j] = fr[j];
|
|
}
|
|
for (y = -RESTORATION_HALFWIN; y <= RESTORATION_HALFWIN; y++) {
|
|
for (x = -RESTORATION_HALFWIN; x <= RESTORATION_HALFWIN; x++) {
|
|
restoration_filters_s[i][y + RESTORATION_HALFWIN]
|
|
[x + RESTORATION_HALFWIN] =
|
|
(uint8_t)(0.5 + RESTORATION_FILT_STEP *
|
|
exp(-(x * x) / (2 * sigma_x_d * sigma_x_d)
|
|
-(y * y) / (2 * sigma_y_d * sigma_y_d)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int vp10_restoration_level_bits(const VP10_COMMON *const cm) {
|
|
return cm->frame_type == KEY_FRAME ?
|
|
RESTORATION_LEVEL_BITS_KF : RESTORATION_LEVEL_BITS;
|
|
}
|
|
|
|
void vp10_loop_restoration_init(RestorationInternal *rst,
|
|
RestorationInfo *rsi, int kf) {
|
|
int i;
|
|
rst->restoration_type = rsi->restoration_type;
|
|
if (rsi->restoration_type == RESTORE_BILATERAL) {
|
|
const int level = rsi->restoration_level;
|
|
assert(level >= 0);
|
|
rst->wr_lut = kf ? restoration_filters_r_kf[level] :
|
|
restoration_filters_r[level];
|
|
for (i = 0; i < RESTORATION_WIN; i++)
|
|
rst->wx_lut[i] = kf ? restoration_filters_s_kf[level][i] :
|
|
restoration_filters_s[level][i];
|
|
} else if (rsi->restoration_type == RESTORE_WIENER) {
|
|
rst->vfilter[RESTORATION_HALFWIN] = rst->hfilter[RESTORATION_HALFWIN] =
|
|
RESTORATION_FILT_STEP;
|
|
for (i = 0; i < RESTORATION_HALFWIN; ++i) {
|
|
rst->vfilter[i] = rst->vfilter[RESTORATION_WIN - 1 - i] = rsi->vfilter[i];
|
|
rst->hfilter[i] = rst->hfilter[RESTORATION_WIN - 1 - i] = rsi->hfilter[i];
|
|
rst->vfilter[RESTORATION_HALFWIN] -= 2 * rsi->vfilter[i];
|
|
rst->hfilter[RESTORATION_HALFWIN] -= 2 * rsi->hfilter[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
static void loop_bilateral_filter(uint8_t *data, int width, int height,
|
|
int stride, RestorationInternal *rst,
|
|
uint8_t *tmpdata, int tmpstride) {
|
|
int i, j;
|
|
const uint8_t *wr_lut_ = rst->wr_lut + RESTORATION_RANGE;
|
|
|
|
uint8_t *data_p = data + RESTORATION_HALFWIN * stride;
|
|
uint8_t *tmpdata_p = tmpdata + RESTORATION_HALFWIN * tmpstride;
|
|
for (i = RESTORATION_HALFWIN; i < height - RESTORATION_HALFWIN; ++i) {
|
|
for (j = RESTORATION_HALFWIN; j < width - RESTORATION_HALFWIN; ++j) {
|
|
int x, y;
|
|
int flsum = 0, wtsum = 0, wt;
|
|
uint8_t *data_p2 = data_p + j - RESTORATION_HALFWIN * stride;
|
|
for (y = -RESTORATION_HALFWIN; y <= RESTORATION_HALFWIN; ++y) {
|
|
for (x = -RESTORATION_HALFWIN; x <= RESTORATION_HALFWIN; ++x) {
|
|
wt = (int)rst->wx_lut[y + RESTORATION_HALFWIN]
|
|
[x + RESTORATION_HALFWIN] *
|
|
(int)wr_lut_[data_p2[x] - data_p[j]];
|
|
wtsum += wt;
|
|
flsum += wt * data_p2[x];
|
|
}
|
|
data_p2 += stride;
|
|
}
|
|
if (wtsum > 0)
|
|
tmpdata_p[j] = clip_pixel((int)((flsum + wtsum / 2) / wtsum));
|
|
else
|
|
tmpdata_p[j] = data_p[j];
|
|
}
|
|
tmpdata_p += tmpstride;
|
|
data_p += stride;
|
|
}
|
|
|
|
for (i = RESTORATION_HALFWIN; i < height - RESTORATION_HALFWIN; ++i) {
|
|
memcpy(data + i * stride + RESTORATION_HALFWIN,
|
|
tmpdata + i * tmpstride + RESTORATION_HALFWIN,
|
|
(width - RESTORATION_HALFWIN * 2) * sizeof(*data));
|
|
}
|
|
}
|
|
|
|
uint8_t hor_sym_filter(uint8_t *d, int *hfilter) {
|
|
int32_t s = (1 << (RESTORATION_FILT_BITS - 1)) +
|
|
d[0] * hfilter[RESTORATION_HALFWIN];
|
|
int i;
|
|
for (i = 1; i <= RESTORATION_HALFWIN; ++i)
|
|
s += (d[i] + d[-i]) * hfilter[RESTORATION_HALFWIN + i];
|
|
return clip_pixel(s >> RESTORATION_FILT_BITS);
|
|
}
|
|
|
|
uint8_t ver_sym_filter(uint8_t *d, int stride, int *vfilter) {
|
|
int32_t s = (1 << (RESTORATION_FILT_BITS - 1)) +
|
|
d[0] * vfilter[RESTORATION_HALFWIN];
|
|
int i;
|
|
for (i = 1; i <= RESTORATION_HALFWIN; ++i)
|
|
s += (d[i * stride] + d[-i * stride]) * vfilter[RESTORATION_HALFWIN + i];
|
|
return clip_pixel(s >> RESTORATION_FILT_BITS);
|
|
}
|
|
|
|
static void loop_wiener_filter(uint8_t *data, int width, int height,
|
|
int stride, RestorationInternal *rst,
|
|
uint8_t *tmpdata, int tmpstride) {
|
|
uint8_t *data_p = data;
|
|
uint8_t *tmpdata_p = tmpdata;
|
|
int i, j;
|
|
|
|
for (i = 0; i < height; ++i) {
|
|
memcpy(tmpdata_p, data_p, sizeof(*data_p) * RESTORATION_HALFWIN);
|
|
data_p += RESTORATION_HALFWIN;
|
|
tmpdata_p += RESTORATION_HALFWIN;
|
|
for (j = RESTORATION_HALFWIN; j < width - RESTORATION_HALFWIN; ++j) {
|
|
*tmpdata_p++ = hor_sym_filter(data_p++, rst->hfilter);
|
|
}
|
|
memcpy(tmpdata_p, data_p, sizeof(*data_p) * RESTORATION_HALFWIN);
|
|
data_p += RESTORATION_HALFWIN - width + stride;
|
|
tmpdata_p += RESTORATION_HALFWIN - width + tmpstride;
|
|
}
|
|
data_p = data;
|
|
tmpdata_p = tmpdata;
|
|
for (i = 0; i < RESTORATION_HALFWIN; ++i) {
|
|
memcpy(data_p, tmpdata_p, sizeof(*data_p) * width);
|
|
data_p += stride;
|
|
tmpdata_p += tmpstride;
|
|
}
|
|
for (; i < height - RESTORATION_HALFWIN; ++i) {
|
|
for (j = 0; j < width; ++j)
|
|
*data_p++ = ver_sym_filter(tmpdata_p++, tmpstride, rst->vfilter);
|
|
data_p += stride - width;
|
|
tmpdata_p += tmpstride - width;
|
|
}
|
|
for (; i < height; ++i) {
|
|
memcpy(data_p, tmpdata_p, sizeof(*data_p) * width);
|
|
data_p += stride;
|
|
tmpdata_p += tmpstride;
|
|
}
|
|
}
|
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
static void loop_bilateral_filter_highbd(
|
|
uint8_t *data8, int width, int height,
|
|
int stride, RestorationInternal *rst,
|
|
uint8_t *tmpdata8, int tmpstride, int bit_depth) {
|
|
int i, j;
|
|
const uint8_t *wr_lut_ = rst->wr_lut + RESTORATION_RANGE;
|
|
|
|
uint16_t *data = CONVERT_TO_SHORTPTR(data8);
|
|
uint16_t *tmpdata = CONVERT_TO_SHORTPTR(tmpdata8);
|
|
uint16_t *data_p = data + RESTORATION_HALFWIN * stride;
|
|
uint16_t *tmpdata_p = tmpdata + RESTORATION_HALFWIN * tmpstride;
|
|
for (i = RESTORATION_HALFWIN; i < height - RESTORATION_HALFWIN; ++i) {
|
|
for (j = RESTORATION_HALFWIN; j < width - RESTORATION_HALFWIN; ++j) {
|
|
int x, y, diff_r;
|
|
int flsum = 0, wtsum = 0, wt;
|
|
uint16_t *data_p2 = data_p + j - RESTORATION_HALFWIN * stride;
|
|
for (y = -RESTORATION_HALFWIN; y <= RESTORATION_HALFWIN; ++y) {
|
|
for (x = -RESTORATION_HALFWIN; x <= RESTORATION_HALFWIN; ++x) {
|
|
diff_r = (data_p2[x] - data_p[j]) >> (bit_depth - 8);
|
|
assert(diff_r >= -RESTORATION_RANGE && diff_r <= RESTORATION_RANGE);
|
|
wt = (int)rst->wx_lut[y + RESTORATION_HALFWIN]
|
|
[x + RESTORATION_HALFWIN] *
|
|
(int)wr_lut_[diff_r];
|
|
wtsum += wt;
|
|
flsum += wt * data_p2[x];
|
|
}
|
|
data_p2 += stride;
|
|
}
|
|
if (wtsum > 0)
|
|
tmpdata_p[j] = clip_pixel_highbd((int)((flsum + wtsum / 2) / wtsum),
|
|
bit_depth);
|
|
else
|
|
tmpdata_p[j] = data_p[j];
|
|
}
|
|
tmpdata_p += tmpstride;
|
|
data_p += stride;
|
|
}
|
|
|
|
for (i = RESTORATION_HALFWIN; i < height - RESTORATION_HALFWIN; ++i) {
|
|
memcpy(data + i * stride + RESTORATION_HALFWIN,
|
|
tmpdata + i * tmpstride + RESTORATION_HALFWIN,
|
|
(width - RESTORATION_HALFWIN * 2) * sizeof(*data));
|
|
}
|
|
}
|
|
|
|
uint16_t hor_sym_filter_highbd(uint16_t *d, int *hfilter, int bd) {
|
|
int32_t s = (1 << (RESTORATION_FILT_BITS - 1)) +
|
|
d[0] * hfilter[RESTORATION_HALFWIN];
|
|
int i;
|
|
for (i = 1; i <= RESTORATION_HALFWIN; ++i)
|
|
s += (d[i] + d[-i]) * hfilter[RESTORATION_HALFWIN + i];
|
|
return clip_pixel_highbd(s >> RESTORATION_FILT_BITS, bd);
|
|
}
|
|
|
|
uint16_t ver_sym_filter_highbd(uint16_t *d, int stride, int *vfilter, int bd) {
|
|
int32_t s = (1 << (RESTORATION_FILT_BITS - 1)) +
|
|
d[0] * vfilter[RESTORATION_HALFWIN];
|
|
int i;
|
|
for (i = 1; i <= RESTORATION_HALFWIN; ++i)
|
|
s += (d[i * stride] + d[-i * stride]) * vfilter[RESTORATION_HALFWIN + i];
|
|
return clip_pixel_highbd(s >> RESTORATION_FILT_BITS, bd);
|
|
}
|
|
|
|
static void loop_wiener_filter_highbd(uint8_t *data8, int width, int height,
|
|
int stride, RestorationInternal *rst,
|
|
uint8_t *tmpdata8, int tmpstride,
|
|
int bit_depth) {
|
|
uint16_t *data = CONVERT_TO_SHORTPTR(data8);
|
|
uint16_t *tmpdata = CONVERT_TO_SHORTPTR(tmpdata8);
|
|
uint16_t *data_p = data;
|
|
uint16_t *tmpdata_p = tmpdata;
|
|
int i, j;
|
|
for (i = 0; i < height; ++i) {
|
|
memcpy(tmpdata_p, data_p, sizeof(*data_p) * RESTORATION_HALFWIN);
|
|
data_p += RESTORATION_HALFWIN;
|
|
tmpdata_p += RESTORATION_HALFWIN;
|
|
for (j = RESTORATION_HALFWIN; j < width - RESTORATION_HALFWIN; ++j) {
|
|
*tmpdata_p++ = hor_sym_filter_highbd(data_p++, rst->hfilter, bit_depth);
|
|
}
|
|
memcpy(tmpdata_p, data_p, sizeof(*data_p) * RESTORATION_HALFWIN);
|
|
data_p += RESTORATION_HALFWIN - width + stride;
|
|
tmpdata_p += RESTORATION_HALFWIN - width + tmpstride;
|
|
}
|
|
data_p = data;
|
|
tmpdata_p = tmpdata;
|
|
for (i = 0; i < RESTORATION_HALFWIN; ++i) {
|
|
memcpy(data_p, tmpdata_p, sizeof(*data_p) * width);
|
|
data_p += stride;
|
|
tmpdata_p += tmpstride;
|
|
}
|
|
for (; i < height - RESTORATION_HALFWIN; ++i) {
|
|
for (j = 0; j < width; ++j)
|
|
*data_p++ = ver_sym_filter_highbd(
|
|
tmpdata_p++, tmpstride, rst->vfilter, bit_depth);
|
|
data_p += stride - width;
|
|
tmpdata_p += tmpstride - width;
|
|
}
|
|
for (; i < height; ++i) {
|
|
memcpy(data_p, tmpdata_p, sizeof(*data_p) * width);
|
|
data_p += stride;
|
|
tmpdata_p += tmpstride;
|
|
}
|
|
}
|
|
#endif // CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
void vp10_loop_restoration_rows(YV12_BUFFER_CONFIG *frame,
|
|
VP10_COMMON *cm,
|
|
int start_mi_row, int end_mi_row,
|
|
int y_only) {
|
|
const int ywidth = frame->y_crop_width;
|
|
const int ystride = frame->y_stride;
|
|
const int uvwidth = frame->uv_crop_width;
|
|
const int uvstride = frame->uv_stride;
|
|
const int ystart = start_mi_row << MI_SIZE_LOG2;
|
|
const int uvstart = ystart >> cm->subsampling_y;
|
|
int yend = end_mi_row << MI_SIZE_LOG2;
|
|
int uvend = yend >> cm->subsampling_y;
|
|
restore_func_type restore_func =
|
|
cm->rst_internal.restoration_type == RESTORE_BILATERAL ?
|
|
loop_bilateral_filter : loop_wiener_filter;
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
restore_func_highbd_type restore_func_highbd =
|
|
cm->rst_internal.restoration_type == RESTORE_BILATERAL ?
|
|
loop_bilateral_filter_highbd : loop_wiener_filter_highbd;
|
|
#endif // CONFIG_VP9_HIGHBITDEPTH
|
|
YV12_BUFFER_CONFIG *tmp_buf;
|
|
|
|
yend = VPXMIN(yend, cm->height);
|
|
uvend = VPXMIN(uvend, cm->subsampling_y ? (cm->height + 1) >> 1 : cm->height);
|
|
|
|
if (vpx_realloc_frame_buffer(&cm->tmp_loop_buf, cm->width, cm->height,
|
|
cm->subsampling_x, cm->subsampling_y,
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
cm->use_highbitdepth,
|
|
#endif
|
|
VP9_DEC_BORDER_IN_PIXELS, cm->byte_alignment,
|
|
NULL, NULL, NULL) < 0)
|
|
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
|
"Failed to allocate tmp restoration buffer");
|
|
|
|
tmp_buf = &cm->tmp_loop_buf;
|
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
if (cm->use_highbitdepth)
|
|
restore_func_highbd(
|
|
frame->y_buffer + ystart * ystride,
|
|
ywidth, yend - ystart, ystride, &cm->rst_internal,
|
|
tmp_buf->y_buffer + ystart * tmp_buf->y_stride,
|
|
tmp_buf->y_stride, cm->bit_depth);
|
|
else
|
|
#endif // CONFIG_VP9_HIGHBITDEPTH
|
|
restore_func(
|
|
frame->y_buffer + ystart * ystride,
|
|
ywidth, yend - ystart, ystride, &cm->rst_internal,
|
|
tmp_buf->y_buffer + ystart * tmp_buf->y_stride,
|
|
tmp_buf->y_stride);
|
|
if (!y_only) {
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
if (cm->use_highbitdepth) {
|
|
restore_func_highbd(
|
|
frame->u_buffer + uvstart * uvstride,
|
|
uvwidth, uvend - uvstart, uvstride, &cm->rst_internal,
|
|
tmp_buf->u_buffer + uvstart * tmp_buf->uv_stride,
|
|
tmp_buf->uv_stride, cm->bit_depth);
|
|
restore_func_highbd(
|
|
frame->v_buffer + uvstart * uvstride,
|
|
uvwidth, uvend - uvstart, uvstride, &cm->rst_internal,
|
|
tmp_buf->v_buffer + uvstart * tmp_buf->uv_stride,
|
|
tmp_buf->uv_stride, cm->bit_depth);
|
|
} else {
|
|
#endif // CONFIG_VP9_HIGHBITDEPTH
|
|
restore_func(
|
|
frame->u_buffer + uvstart * uvstride,
|
|
uvwidth, uvend - uvstart, uvstride, &cm->rst_internal,
|
|
tmp_buf->u_buffer + uvstart * tmp_buf->uv_stride,
|
|
tmp_buf->uv_stride);
|
|
restore_func(
|
|
frame->v_buffer + uvstart * uvstride,
|
|
uvwidth, uvend - uvstart, uvstride, &cm->rst_internal,
|
|
tmp_buf->v_buffer + uvstart * tmp_buf->uv_stride,
|
|
tmp_buf->uv_stride);
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
}
|
|
#endif // CONFIG_VP9_HIGHBITDEPTH
|
|
}
|
|
}
|
|
|
|
void vp10_loop_restoration_frame(YV12_BUFFER_CONFIG *frame,
|
|
VP10_COMMON *cm,
|
|
RestorationInfo *rsi,
|
|
int y_only, int partial_frame) {
|
|
int start_mi_row, end_mi_row, mi_rows_to_filter;
|
|
if (rsi->restoration_type != RESTORE_NONE) {
|
|
start_mi_row = 0;
|
|
mi_rows_to_filter = cm->mi_rows;
|
|
if (partial_frame && cm->mi_rows > 8) {
|
|
start_mi_row = cm->mi_rows >> 1;
|
|
start_mi_row &= 0xfffffff8;
|
|
mi_rows_to_filter = VPXMAX(cm->mi_rows / 8, 8);
|
|
}
|
|
end_mi_row = start_mi_row + mi_rows_to_filter;
|
|
vp10_loop_restoration_init(&cm->rst_internal, rsi,
|
|
cm->frame_type == KEY_FRAME);
|
|
vp10_loop_restoration_rows(frame, cm, start_mi_row, end_mi_row, y_only);
|
|
}
|
|
}
|