diff options
Diffstat (limited to 'third_party/aom/av1/common/warped_motion.c')
-rw-r--r-- | third_party/aom/av1/common/warped_motion.c | 1048 |
1 files changed, 214 insertions, 834 deletions
diff --git a/third_party/aom/av1/common/warped_motion.c b/third_party/aom/av1/common/warped_motion.c index 34374af69a..ae6f076572 100644 --- a/third_party/aom/av1/common/warped_motion.c +++ b/third_party/aom/av1/common/warped_motion.c @@ -15,7 +15,8 @@ #include <math.h> #include <assert.h> -#include "./av1_rtcd.h" +#include "config/av1_rtcd.h" + #include "av1/common/warped_motion.h" #include "av1/common/scale.h" @@ -91,78 +92,11 @@ static const int error_measure_lut[512] = { }; /* clang-format on */ -static ProjectPointsFunc get_project_points_type(TransformationType type) { - switch (type) { - case VERTRAPEZOID: return project_points_vertrapezoid; - case HORTRAPEZOID: return project_points_hortrapezoid; - case HOMOGRAPHY: return project_points_homography; - case AFFINE: return project_points_affine; - case ROTZOOM: return project_points_rotzoom; - case TRANSLATION: return project_points_translation; - default: assert(0); return NULL; - } -} - -void project_points_translation(const int32_t *mat, int *points, int *proj, - const int n, const int stride_points, - const int stride_proj, const int subsampling_x, - const int subsampling_y) { - int i; - for (i = 0; i < n; ++i) { - const int x = *(points++), y = *(points++); - if (subsampling_x) - *(proj++) = ROUND_POWER_OF_TWO_SIGNED( - ((x * (1 << (WARPEDMODEL_PREC_BITS + 1))) + mat[0]), - WARPEDDIFF_PREC_BITS + 1); - else - *(proj++) = ROUND_POWER_OF_TWO_SIGNED( - ((x * (1 << WARPEDMODEL_PREC_BITS)) + mat[0]), WARPEDDIFF_PREC_BITS); - if (subsampling_y) - *(proj++) = ROUND_POWER_OF_TWO_SIGNED( - ((y * (1 << (WARPEDMODEL_PREC_BITS + 1))) + mat[1]), - WARPEDDIFF_PREC_BITS + 1); - else - *(proj++) = ROUND_POWER_OF_TWO_SIGNED( - ((y * (1 << WARPEDMODEL_PREC_BITS))) + mat[1], WARPEDDIFF_PREC_BITS); - points += stride_points - 2; - proj += stride_proj - 2; - } -} - -void project_points_rotzoom(const int32_t *mat, int *points, int *proj, - const int n, const int stride_points, - const int stride_proj, const int subsampling_x, - const int subsampling_y) { - int i; - for (i = 0; i < n; ++i) { - const int x = *(points++), y = *(points++); - if (subsampling_x) - *(proj++) = ROUND_POWER_OF_TWO_SIGNED( - mat[2] * 2 * x + mat[3] * 2 * y + mat[0] + - (mat[2] + mat[3] - (1 << WARPEDMODEL_PREC_BITS)) / 2, - WARPEDDIFF_PREC_BITS + 1); - else - *(proj++) = ROUND_POWER_OF_TWO_SIGNED(mat[2] * x + mat[3] * y + mat[0], - WARPEDDIFF_PREC_BITS); - if (subsampling_y) - *(proj++) = ROUND_POWER_OF_TWO_SIGNED( - -mat[3] * 2 * x + mat[2] * 2 * y + mat[1] + - (-mat[3] + mat[2] - (1 << WARPEDMODEL_PREC_BITS)) / 2, - WARPEDDIFF_PREC_BITS + 1); - else - *(proj++) = ROUND_POWER_OF_TWO_SIGNED(-mat[3] * x + mat[2] * y + mat[1], - WARPEDDIFF_PREC_BITS); - points += stride_points - 2; - proj += stride_proj - 2; - } -} - void project_points_affine(const int32_t *mat, int *points, int *proj, const int n, const int stride_points, const int stride_proj, const int subsampling_x, const int subsampling_y) { - int i; - for (i = 0; i < n; ++i) { + for (int i = 0; i < n; ++i) { const int x = *(points++), y = *(points++); if (subsampling_x) *(proj++) = ROUND_POWER_OF_TWO_SIGNED( @@ -185,301 +119,6 @@ void project_points_affine(const int32_t *mat, int *points, int *proj, } } -void project_points_hortrapezoid(const int32_t *mat, int *points, int *proj, - const int n, const int stride_points, - const int stride_proj, const int subsampling_x, - const int subsampling_y) { - int i; - int64_t x, y, Z; - int64_t xp, yp; - for (i = 0; i < n; ++i) { - x = *(points++), y = *(points++); - x = (subsampling_x ? 4 * x + 1 : 2 * x); - y = (subsampling_y ? 4 * y + 1 : 2 * y); - - Z = (mat[7] * y + (1 << (WARPEDMODEL_ROW3HOMO_PREC_BITS + 1))); - xp = (mat[2] * x + mat[3] * y + 2 * mat[0]) * - (1 << (WARPEDPIXEL_PREC_BITS + WARPEDMODEL_ROW3HOMO_PREC_BITS - - WARPEDMODEL_PREC_BITS)); - yp = (mat[5] * y + 2 * mat[1]) * - (1 << (WARPEDPIXEL_PREC_BITS + WARPEDMODEL_ROW3HOMO_PREC_BITS - - WARPEDMODEL_PREC_BITS)); - - xp = xp > 0 ? (xp + Z / 2) / Z : (xp - Z / 2) / Z; - yp = yp > 0 ? (yp + Z / 2) / Z : (yp - Z / 2) / Z; - - if (subsampling_x) xp = (xp - (1 << (WARPEDPIXEL_PREC_BITS - 1))) / 2; - if (subsampling_y) yp = (yp - (1 << (WARPEDPIXEL_PREC_BITS - 1))) / 2; - *(proj++) = (int)xp; - *(proj++) = (int)yp; - - points += stride_points - 2; - proj += stride_proj - 2; - } -} - -void project_points_vertrapezoid(const int32_t *mat, int *points, int *proj, - const int n, const int stride_points, - const int stride_proj, const int subsampling_x, - const int subsampling_y) { - int i; - int64_t x, y, Z; - int64_t xp, yp; - for (i = 0; i < n; ++i) { - x = *(points++), y = *(points++); - x = (subsampling_x ? 4 * x + 1 : 2 * x); - y = (subsampling_y ? 4 * y + 1 : 2 * y); - - Z = (mat[6] * x + (1 << (WARPEDMODEL_ROW3HOMO_PREC_BITS + 1))); - xp = (mat[2] * x + 2 * mat[0]) * - (1 << (WARPEDPIXEL_PREC_BITS + WARPEDMODEL_ROW3HOMO_PREC_BITS - - WARPEDMODEL_PREC_BITS)); - yp = (mat[4] * x + mat[5] * y + 2 * mat[1]) * - (1 << (WARPEDPIXEL_PREC_BITS + WARPEDMODEL_ROW3HOMO_PREC_BITS - - WARPEDMODEL_PREC_BITS)); - - xp = xp > 0 ? (xp + Z / 2) / Z : (xp - Z / 2) / Z; - yp = yp > 0 ? (yp + Z / 2) / Z : (yp - Z / 2) / Z; - - if (subsampling_x) xp = (xp - (1 << (WARPEDPIXEL_PREC_BITS - 1))) / 2; - if (subsampling_y) yp = (yp - (1 << (WARPEDPIXEL_PREC_BITS - 1))) / 2; - *(proj++) = (int)xp; - *(proj++) = (int)yp; - - points += stride_points - 2; - proj += stride_proj - 2; - } -} - -void project_points_homography(const int32_t *mat, int *points, int *proj, - const int n, const int stride_points, - const int stride_proj, const int subsampling_x, - const int subsampling_y) { - int i; - int64_t x, y, Z; - int64_t xp, yp; - for (i = 0; i < n; ++i) { - x = *(points++), y = *(points++); - x = (subsampling_x ? 4 * x + 1 : 2 * x); - y = (subsampling_y ? 4 * y + 1 : 2 * y); - - Z = (mat[6] * x + mat[7] * y + (1 << (WARPEDMODEL_ROW3HOMO_PREC_BITS + 1))); - xp = (mat[2] * x + mat[3] * y + 2 * mat[0]) * - (1 << (WARPEDPIXEL_PREC_BITS + WARPEDMODEL_ROW3HOMO_PREC_BITS - - WARPEDMODEL_PREC_BITS)); - yp = (mat[4] * x + mat[5] * y + 2 * mat[1]) * - (1 << (WARPEDPIXEL_PREC_BITS + WARPEDMODEL_ROW3HOMO_PREC_BITS - - WARPEDMODEL_PREC_BITS)); - - xp = xp > 0 ? (xp + Z / 2) / Z : (xp - Z / 2) / Z; - yp = yp > 0 ? (yp + Z / 2) / Z : (yp - Z / 2) / Z; - - if (subsampling_x) xp = (xp - (1 << (WARPEDPIXEL_PREC_BITS - 1))) / 2; - if (subsampling_y) yp = (yp - (1 << (WARPEDPIXEL_PREC_BITS - 1))) / 2; - *(proj++) = (int)xp; - *(proj++) = (int)yp; - - points += stride_points - 2; - proj += stride_proj - 2; - } -} - -static const int16_t - filter_ntap[WARPEDPIXEL_PREC_SHIFTS][WARPEDPIXEL_FILTER_TAPS] = { -#if WARPEDPIXEL_PREC_BITS == 6 - { 0, 0, 128, 0, 0, 0 }, { 0, -1, 128, 2, -1, 0 }, - { 1, -3, 127, 4, -1, 0 }, { 1, -4, 126, 6, -2, 1 }, - { 1, -5, 126, 8, -3, 1 }, { 1, -6, 125, 11, -4, 1 }, - { 1, -7, 124, 13, -4, 1 }, { 2, -8, 123, 15, -5, 1 }, - { 2, -9, 122, 18, -6, 1 }, { 2, -10, 121, 20, -6, 1 }, - { 2, -11, 120, 22, -7, 2 }, { 2, -12, 119, 25, -8, 2 }, - { 3, -13, 117, 27, -8, 2 }, { 3, -13, 116, 29, -9, 2 }, - { 3, -14, 114, 32, -10, 3 }, { 3, -15, 113, 35, -10, 2 }, - { 3, -15, 111, 37, -11, 3 }, { 3, -16, 109, 40, -11, 3 }, - { 3, -16, 108, 42, -12, 3 }, { 4, -17, 106, 45, -13, 3 }, - { 4, -17, 104, 47, -13, 3 }, { 4, -17, 102, 50, -14, 3 }, - { 4, -17, 100, 52, -14, 3 }, { 4, -18, 98, 55, -15, 4 }, - { 4, -18, 96, 58, -15, 3 }, { 4, -18, 94, 60, -16, 4 }, - { 4, -18, 91, 63, -16, 4 }, { 4, -18, 89, 65, -16, 4 }, - { 4, -18, 87, 68, -17, 4 }, { 4, -18, 85, 70, -17, 4 }, - { 4, -18, 82, 73, -17, 4 }, { 4, -18, 80, 75, -17, 4 }, - { 4, -18, 78, 78, -18, 4 }, { 4, -17, 75, 80, -18, 4 }, - { 4, -17, 73, 82, -18, 4 }, { 4, -17, 70, 85, -18, 4 }, - { 4, -17, 68, 87, -18, 4 }, { 4, -16, 65, 89, -18, 4 }, - { 4, -16, 63, 91, -18, 4 }, { 4, -16, 60, 94, -18, 4 }, - { 3, -15, 58, 96, -18, 4 }, { 4, -15, 55, 98, -18, 4 }, - { 3, -14, 52, 100, -17, 4 }, { 3, -14, 50, 102, -17, 4 }, - { 3, -13, 47, 104, -17, 4 }, { 3, -13, 45, 106, -17, 4 }, - { 3, -12, 42, 108, -16, 3 }, { 3, -11, 40, 109, -16, 3 }, - { 3, -11, 37, 111, -15, 3 }, { 2, -10, 35, 113, -15, 3 }, - { 3, -10, 32, 114, -14, 3 }, { 2, -9, 29, 116, -13, 3 }, - { 2, -8, 27, 117, -13, 3 }, { 2, -8, 25, 119, -12, 2 }, - { 2, -7, 22, 120, -11, 2 }, { 1, -6, 20, 121, -10, 2 }, - { 1, -6, 18, 122, -9, 2 }, { 1, -5, 15, 123, -8, 2 }, - { 1, -4, 13, 124, -7, 1 }, { 1, -4, 11, 125, -6, 1 }, - { 1, -3, 8, 126, -5, 1 }, { 1, -2, 6, 126, -4, 1 }, - { 0, -1, 4, 127, -3, 1 }, { 0, -1, 2, 128, -1, 0 }, -#elif WARPEDPIXEL_PREC_BITS == 5 - { 0, 0, 128, 0, 0, 0 }, { 1, -3, 127, 4, -1, 0 }, - { 1, -5, 126, 8, -3, 1 }, { 1, -7, 124, 13, -4, 1 }, - { 2, -9, 122, 18, -6, 1 }, { 2, -11, 120, 22, -7, 2 }, - { 3, -13, 117, 27, -8, 2 }, { 3, -14, 114, 32, -10, 3 }, - { 3, -15, 111, 37, -11, 3 }, { 3, -16, 108, 42, -12, 3 }, - { 4, -17, 104, 47, -13, 3 }, { 4, -17, 100, 52, -14, 3 }, - { 4, -18, 96, 58, -15, 3 }, { 4, -18, 91, 63, -16, 4 }, - { 4, -18, 87, 68, -17, 4 }, { 4, -18, 82, 73, -17, 4 }, - { 4, -18, 78, 78, -18, 4 }, { 4, -17, 73, 82, -18, 4 }, - { 4, -17, 68, 87, -18, 4 }, { 4, -16, 63, 91, -18, 4 }, - { 3, -15, 58, 96, -18, 4 }, { 3, -14, 52, 100, -17, 4 }, - { 3, -13, 47, 104, -17, 4 }, { 3, -12, 42, 108, -16, 3 }, - { 3, -11, 37, 111, -15, 3 }, { 3, -10, 32, 114, -14, 3 }, - { 2, -8, 27, 117, -13, 3 }, { 2, -7, 22, 120, -11, 2 }, - { 1, -6, 18, 122, -9, 2 }, { 1, -4, 13, 124, -7, 1 }, - { 1, -3, 8, 126, -5, 1 }, { 0, -1, 4, 127, -3, 1 }, -#endif // WARPEDPIXEL_PREC_BITS == 6 - }; - -static int32_t do_ntap_filter(const int32_t *const p, int x) { - int i; - int32_t sum = 0; - for (i = 0; i < WARPEDPIXEL_FILTER_TAPS; ++i) { - sum += p[i - WARPEDPIXEL_FILTER_TAPS / 2 + 1] * filter_ntap[x][i]; - } - return sum; -} - -static int32_t do_cubic_filter(const int32_t *const p, int x) { - if (x == 0) { - return p[0] * (1 << WARPEDPIXEL_FILTER_BITS); - } else if (x == (1 << WARPEDPIXEL_PREC_BITS)) { - return p[1] * (1 << WARPEDPIXEL_FILTER_BITS); - } else { - const int64_t v1 = (int64_t)x * x * x * (3 * (p[0] - p[1]) + p[2] - p[-1]); - const int64_t v2 = - (int64_t)x * x * (2 * p[-1] - 5 * p[0] + 4 * p[1] - p[2]); - const int64_t v3 = x * (p[1] - p[-1]); - const int64_t v4 = 2 * p[0]; - return (int32_t)ROUND_POWER_OF_TWO_SIGNED( - (v4 * (1 << (3 * WARPEDPIXEL_PREC_BITS))) + - (v3 * (1 << (2 * WARPEDPIXEL_PREC_BITS))) + - (v2 * (1 << WARPEDPIXEL_PREC_BITS)) + v1, - 3 * WARPEDPIXEL_PREC_BITS + 1 - WARPEDPIXEL_FILTER_BITS); - } -} - -static INLINE void get_subcolumn(int taps, const uint8_t *const ref, - int32_t *col, int stride, int x, int y_start) { - int i; - for (i = 0; i < taps; ++i) { - col[i] = ref[(i + y_start) * stride + x]; - } -} - -static uint8_t bi_ntap_filter(const uint8_t *const ref, int x, int y, - int stride) { - int32_t val, arr[WARPEDPIXEL_FILTER_TAPS]; - int k; - const int i = (int)x >> WARPEDPIXEL_PREC_BITS; - const int j = (int)y >> WARPEDPIXEL_PREC_BITS; - for (k = 0; k < WARPEDPIXEL_FILTER_TAPS; ++k) { - int32_t arr_temp[WARPEDPIXEL_FILTER_TAPS]; - get_subcolumn(WARPEDPIXEL_FILTER_TAPS, ref, arr_temp, stride, - i + k + 1 - WARPEDPIXEL_FILTER_TAPS / 2, - j + 1 - WARPEDPIXEL_FILTER_TAPS / 2); - arr[k] = do_ntap_filter(arr_temp + WARPEDPIXEL_FILTER_TAPS / 2 - 1, - y - (j * (1 << WARPEDPIXEL_PREC_BITS))); - } - val = do_ntap_filter(arr + WARPEDPIXEL_FILTER_TAPS / 2 - 1, - x - (i * (1 << WARPEDPIXEL_PREC_BITS))); - val = ROUND_POWER_OF_TWO_SIGNED(val, WARPEDPIXEL_FILTER_BITS * 2); - return (uint8_t)clip_pixel(val); -} - -static uint8_t bi_cubic_filter(const uint8_t *const ref, int x, int y, - int stride) { - int32_t val, arr[4]; - int k; - const int i = (int)x >> WARPEDPIXEL_PREC_BITS; - const int j = (int)y >> WARPEDPIXEL_PREC_BITS; - for (k = 0; k < 4; ++k) { - int32_t arr_temp[4]; - get_subcolumn(4, ref, arr_temp, stride, i + k - 1, j - 1); - arr[k] = - do_cubic_filter(arr_temp + 1, y - (j * (1 << WARPEDPIXEL_PREC_BITS))); - } - val = do_cubic_filter(arr + 1, x - (i * (1 << WARPEDPIXEL_PREC_BITS))); - val = ROUND_POWER_OF_TWO_SIGNED(val, WARPEDPIXEL_FILTER_BITS * 2); - return (uint8_t)clip_pixel(val); -} - -static uint8_t bi_linear_filter(const uint8_t *const ref, int x, int y, - int stride) { - const int ix = x >> WARPEDPIXEL_PREC_BITS; - const int iy = y >> WARPEDPIXEL_PREC_BITS; - const int sx = x - (ix * (1 << WARPEDPIXEL_PREC_BITS)); - const int sy = y - (iy * (1 << WARPEDPIXEL_PREC_BITS)); - int32_t val; - val = ROUND_POWER_OF_TWO_SIGNED( - ref[iy * stride + ix] * (WARPEDPIXEL_PREC_SHIFTS - sy) * - (WARPEDPIXEL_PREC_SHIFTS - sx) + - ref[iy * stride + ix + 1] * (WARPEDPIXEL_PREC_SHIFTS - sy) * sx + - ref[(iy + 1) * stride + ix] * sy * (WARPEDPIXEL_PREC_SHIFTS - sx) + - ref[(iy + 1) * stride + ix + 1] * sy * sx, - WARPEDPIXEL_PREC_BITS * 2); - return (uint8_t)clip_pixel(val); -} - -static uint8_t warp_interpolate(const uint8_t *const ref, int x, int y, - int width, int height, int stride) { - const int ix = x >> WARPEDPIXEL_PREC_BITS; - const int iy = y >> WARPEDPIXEL_PREC_BITS; - const int sx = x - (ix * (1 << WARPEDPIXEL_PREC_BITS)); - const int sy = y - (iy * (1 << WARPEDPIXEL_PREC_BITS)); - int32_t v; - - if (ix < 0 && iy < 0) - return ref[0]; - else if (ix < 0 && iy >= height - 1) - return ref[(height - 1) * stride]; - else if (ix >= width - 1 && iy < 0) - return ref[width - 1]; - else if (ix >= width - 1 && iy >= height - 1) - return ref[(height - 1) * stride + (width - 1)]; - else if (ix < 0) { - v = ROUND_POWER_OF_TWO_SIGNED( - ref[iy * stride] * (WARPEDPIXEL_PREC_SHIFTS - sy) + - ref[(iy + 1) * stride] * sy, - WARPEDPIXEL_PREC_BITS); - return clip_pixel(v); - } else if (iy < 0) { - v = ROUND_POWER_OF_TWO_SIGNED( - ref[ix] * (WARPEDPIXEL_PREC_SHIFTS - sx) + ref[ix + 1] * sx, - WARPEDPIXEL_PREC_BITS); - return clip_pixel(v); - } else if (ix >= width - 1) { - v = ROUND_POWER_OF_TWO_SIGNED( - ref[iy * stride + width - 1] * (WARPEDPIXEL_PREC_SHIFTS - sy) + - ref[(iy + 1) * stride + width - 1] * sy, - WARPEDPIXEL_PREC_BITS); - return clip_pixel(v); - } else if (iy >= height - 1) { - v = ROUND_POWER_OF_TWO_SIGNED( - ref[(height - 1) * stride + ix] * (WARPEDPIXEL_PREC_SHIFTS - sx) + - ref[(height - 1) * stride + ix + 1] * sx, - WARPEDPIXEL_PREC_BITS); - return clip_pixel(v); - } else if (ix >= WARPEDPIXEL_FILTER_TAPS / 2 - 1 && - iy >= WARPEDPIXEL_FILTER_TAPS / 2 - 1 && - ix < width - WARPEDPIXEL_FILTER_TAPS / 2 && - iy < height - WARPEDPIXEL_FILTER_TAPS / 2) { - return bi_ntap_filter(ref, x, y, stride); - } else if (ix >= 1 && iy >= 1 && ix < width - 2 && iy < height - 2) { - return bi_cubic_filter(ref, x, y, stride); - } else { - return bi_linear_filter(ref, x, y, stride); - } -} - // For warping, we really use a 6-tap filter, but we do blocks of 8 pixels // at a time. The zoom/rotation/shear in the model are applied to the // "fractional" position of each pixel, which therefore varies within @@ -683,15 +322,14 @@ static const uint16_t div_lut[DIV_LUT_NUM + 1] = { 8240, 8224, 8208, 8192, }; -#if CONFIG_WARPED_MOTION // Decomposes a divisor D such that 1/D = y/2^shift, where y is returned // at precision of DIV_LUT_PREC_BITS along with the shift. static int16_t resolve_divisor_64(uint64_t D, int16_t *shift) { - int64_t e, f; + int64_t f; *shift = (int16_t)((D >> 32) ? get_msb((unsigned int)(D >> 32)) + 32 : get_msb((unsigned int)D)); // e is obtained from D after resetting the most significant 1 bit. - e = D - ((uint64_t)1 << *shift); + const int64_t e = D - ((uint64_t)1 << *shift); // Get the most significant DIV_LUT_BITS (8) bits of e into f if (*shift > DIV_LUT_BITS) f = ROUND_POWER_OF_TWO_64(e, *shift - DIV_LUT_BITS); @@ -702,13 +340,12 @@ static int16_t resolve_divisor_64(uint64_t D, int16_t *shift) { // Use f as lookup into the precomputed table of multipliers return div_lut[f]; } -#endif // CONFIG_WARPED_MOTION static int16_t resolve_divisor_32(uint32_t D, int16_t *shift) { - int32_t e, f; + int32_t f; *shift = get_msb(D); // e is obtained from D after resetting the most significant 1 bit. - e = D - ((uint32_t)1 << *shift); + const int32_t e = D - ((uint32_t)1 << *shift); // Get the most significant DIV_LUT_BITS (8) bits of e into f if (*shift > DIV_LUT_BITS) f = ROUND_POWER_OF_TWO(e, *shift - DIV_LUT_BITS); @@ -743,16 +380,13 @@ int get_shear_params(WarpedMotionParams *wm) { wm->beta = clamp(mat[3], INT16_MIN, INT16_MAX); int16_t shift; int16_t y = resolve_divisor_32(abs(mat[2]), &shift) * (mat[2] < 0 ? -1 : 1); - int64_t v; - v = ((int64_t)mat[4] * (1 << WARPEDMODEL_PREC_BITS)) * y; + int64_t v = ((int64_t)mat[4] * (1 << WARPEDMODEL_PREC_BITS)) * y; wm->gamma = clamp((int)ROUND_POWER_OF_TWO_SIGNED_64(v, shift), INT16_MIN, INT16_MAX); v = ((int64_t)mat[3] * mat[4]) * y; wm->delta = clamp(mat[5] - (int)ROUND_POWER_OF_TWO_SIGNED_64(v, shift) - (1 << WARPEDMODEL_PREC_BITS), INT16_MIN, INT16_MAX); - if (!is_affine_shear_allowed(wm->alpha, wm->beta, wm->gamma, wm->delta)) - return 0; wm->alpha = ROUND_POWER_OF_TWO_SIGNED(wm->alpha, WARP_PARAM_REDUCE_BITS) * (1 << WARP_PARAM_REDUCE_BITS); @@ -762,171 +396,24 @@ int get_shear_params(WarpedMotionParams *wm) { (1 << WARP_PARAM_REDUCE_BITS); wm->delta = ROUND_POWER_OF_TWO_SIGNED(wm->delta, WARP_PARAM_REDUCE_BITS) * (1 << WARP_PARAM_REDUCE_BITS); - return 1; -} - -#if CONFIG_HIGHBITDEPTH -static INLINE void highbd_get_subcolumn(int taps, const uint16_t *const ref, - int32_t *col, int stride, int x, - int y_start) { - int i; - for (i = 0; i < taps; ++i) { - col[i] = ref[(i + y_start) * stride + x]; - } -} - -static uint16_t highbd_bi_ntap_filter(const uint16_t *const ref, int x, int y, - int stride, int bd) { - int32_t val, arr[WARPEDPIXEL_FILTER_TAPS]; - int k; - const int i = (int)x >> WARPEDPIXEL_PREC_BITS; - const int j = (int)y >> WARPEDPIXEL_PREC_BITS; - for (k = 0; k < WARPEDPIXEL_FILTER_TAPS; ++k) { - int32_t arr_temp[WARPEDPIXEL_FILTER_TAPS]; - highbd_get_subcolumn(WARPEDPIXEL_FILTER_TAPS, ref, arr_temp, stride, - i + k + 1 - WARPEDPIXEL_FILTER_TAPS / 2, - j + 1 - WARPEDPIXEL_FILTER_TAPS / 2); - arr[k] = do_ntap_filter(arr_temp + WARPEDPIXEL_FILTER_TAPS / 2 - 1, - y - (j * (1 << WARPEDPIXEL_PREC_BITS))); - } - val = do_ntap_filter(arr + WARPEDPIXEL_FILTER_TAPS / 2 - 1, - x - (i * (1 << WARPEDPIXEL_PREC_BITS))); - val = ROUND_POWER_OF_TWO_SIGNED(val, WARPEDPIXEL_FILTER_BITS * 2); - return (uint16_t)clip_pixel_highbd(val, bd); -} - -static uint16_t highbd_bi_cubic_filter(const uint16_t *const ref, int x, int y, - int stride, int bd) { - int32_t val, arr[4]; - int k; - const int i = (int)x >> WARPEDPIXEL_PREC_BITS; - const int j = (int)y >> WARPEDPIXEL_PREC_BITS; - for (k = 0; k < 4; ++k) { - int32_t arr_temp[4]; - highbd_get_subcolumn(4, ref, arr_temp, stride, i + k - 1, j - 1); - arr[k] = - do_cubic_filter(arr_temp + 1, y - (j * (1 << WARPEDPIXEL_PREC_BITS))); - } - val = do_cubic_filter(arr + 1, x - (i * (1 << WARPEDPIXEL_PREC_BITS))); - val = ROUND_POWER_OF_TWO_SIGNED(val, WARPEDPIXEL_FILTER_BITS * 2); - return (uint16_t)clip_pixel_highbd(val, bd); -} -static uint16_t highbd_bi_linear_filter(const uint16_t *const ref, int x, int y, - int stride, int bd) { - const int ix = x >> WARPEDPIXEL_PREC_BITS; - const int iy = y >> WARPEDPIXEL_PREC_BITS; - const int sx = x - (ix * (1 << WARPEDPIXEL_PREC_BITS)); - const int sy = y - (iy * (1 << WARPEDPIXEL_PREC_BITS)); - int32_t val; - val = ROUND_POWER_OF_TWO_SIGNED( - ref[iy * stride + ix] * (WARPEDPIXEL_PREC_SHIFTS - sy) * - (WARPEDPIXEL_PREC_SHIFTS - sx) + - ref[iy * stride + ix + 1] * (WARPEDPIXEL_PREC_SHIFTS - sy) * sx + - ref[(iy + 1) * stride + ix] * sy * (WARPEDPIXEL_PREC_SHIFTS - sx) + - ref[(iy + 1) * stride + ix + 1] * sy * sx, - WARPEDPIXEL_PREC_BITS * 2); - return (uint16_t)clip_pixel_highbd(val, bd); -} + if (!is_affine_shear_allowed(wm->alpha, wm->beta, wm->gamma, wm->delta)) + return 0; -static uint16_t highbd_warp_interpolate(const uint16_t *const ref, int x, int y, - int width, int height, int stride, - int bd) { - const int ix = x >> WARPEDPIXEL_PREC_BITS; - const int iy = y >> WARPEDPIXEL_PREC_BITS; - const int sx = x - (ix * (1 << WARPEDPIXEL_PREC_BITS)); - const int sy = y - (iy * (1 << WARPEDPIXEL_PREC_BITS)); - int32_t v; - - if (ix < 0 && iy < 0) - return ref[0]; - else if (ix < 0 && iy > height - 1) - return ref[(height - 1) * stride]; - else if (ix > width - 1 && iy < 0) - return ref[width - 1]; - else if (ix > width - 1 && iy > height - 1) - return ref[(height - 1) * stride + (width - 1)]; - else if (ix < 0) { - v = ROUND_POWER_OF_TWO_SIGNED( - ref[iy * stride] * (WARPEDPIXEL_PREC_SHIFTS - sy) + - ref[(iy + 1) * stride] * sy, - WARPEDPIXEL_PREC_BITS); - return clip_pixel_highbd(v, bd); - } else if (iy < 0) { - v = ROUND_POWER_OF_TWO_SIGNED( - ref[ix] * (WARPEDPIXEL_PREC_SHIFTS - sx) + ref[ix + 1] * sx, - WARPEDPIXEL_PREC_BITS); - return clip_pixel_highbd(v, bd); - } else if (ix > width - 1) { - v = ROUND_POWER_OF_TWO_SIGNED( - ref[iy * stride + width - 1] * (WARPEDPIXEL_PREC_SHIFTS - sy) + - ref[(iy + 1) * stride + width - 1] * sy, - WARPEDPIXEL_PREC_BITS); - return clip_pixel_highbd(v, bd); - } else if (iy > height - 1) { - v = ROUND_POWER_OF_TWO_SIGNED( - ref[(height - 1) * stride + ix] * (WARPEDPIXEL_PREC_SHIFTS - sx) + - ref[(height - 1) * stride + ix + 1] * sx, - WARPEDPIXEL_PREC_BITS); - return clip_pixel_highbd(v, bd); - } else if (ix >= WARPEDPIXEL_FILTER_TAPS / 2 - 1 && - iy >= WARPEDPIXEL_FILTER_TAPS / 2 - 1 && - ix < width - WARPEDPIXEL_FILTER_TAPS / 2 && - iy < height - WARPEDPIXEL_FILTER_TAPS / 2) { - return highbd_bi_ntap_filter(ref, x, y, stride, bd); - } else if (ix >= 1 && iy >= 1 && ix < width - 2 && iy < height - 2) { - return highbd_bi_cubic_filter(ref, x, y, stride, bd); - } else { - return highbd_bi_linear_filter(ref, x, y, stride, bd); - } + return 1; } static INLINE int highbd_error_measure(int err, int bd) { const int b = bd - 8; const int bmask = (1 << b) - 1; const int v = (1 << b); - int e1, e2; err = abs(err); - e1 = err >> b; - e2 = err & bmask; + const int e1 = err >> b; + const int e2 = err & bmask; return error_measure_lut[255 + e1] * (v - e2) + error_measure_lut[256 + e1] * e2; } -static void highbd_warp_plane_old(const WarpedMotionParams *const wm, - const uint8_t *const ref8, int width, - int height, int stride, - const uint8_t *const pred8, int p_col, - int p_row, int p_width, int p_height, - int p_stride, int subsampling_x, - int subsampling_y, int x_scale, int y_scale, - int bd, ConvolveParams *conv_params) { - int i, j; - ProjectPointsFunc projectpoints = get_project_points_type(wm->wmtype); - uint16_t *pred = CONVERT_TO_SHORTPTR(pred8); - const uint16_t *const ref = CONVERT_TO_SHORTPTR(ref8); - if (projectpoints == NULL) return; - for (i = p_row; i < p_row + p_height; ++i) { - for (j = p_col; j < p_col + p_width; ++j) { - int in[2], out[2]; - in[0] = j; - in[1] = i; - projectpoints(wm->wmmat, in, out, 1, 2, 2, subsampling_x, subsampling_y); - out[0] = ROUND_POWER_OF_TWO_SIGNED(out[0] * x_scale, SCALE_SUBPEL_BITS); - out[1] = ROUND_POWER_OF_TWO_SIGNED(out[1] * y_scale, SCALE_SUBPEL_BITS); - if (conv_params->do_average) - pred[(j - p_col) + (i - p_row) * p_stride] = ROUND_POWER_OF_TWO( - pred[(j - p_col) + (i - p_row) * p_stride] + - highbd_warp_interpolate(ref, out[0], out[1], width, height, - stride, bd), - 1); - else - pred[(j - p_col) + (i - p_row) * p_stride] = highbd_warp_interpolate( - ref, out[0], out[1], width, height, stride, bd); - } - } -} - /* Note: For an explanation of the warp algorithm, and some notes on bit widths for hardware implementations, see the comments above av1_warp_affine_c */ @@ -938,37 +425,23 @@ void av1_highbd_warp_affine_c(const int32_t *mat, const uint16_t *ref, ConvolveParams *conv_params, int16_t alpha, int16_t beta, int16_t gamma, int16_t delta) { int32_t tmp[15 * 8]; - int i, j, k, l, m; -#if CONFIG_CONVOLVE_ROUND - const int use_conv_params = conv_params->round == CONVOLVE_OPT_NO_ROUND; const int reduce_bits_horiz = - use_conv_params ? conv_params->round_0 : HORSHEAR_REDUCE_PREC_BITS; - const int max_bits_horiz = - use_conv_params - ? bd + FILTER_BITS + 1 - conv_params->round_0 - : bd + WARPEDPIXEL_FILTER_BITS + 1 - HORSHEAR_REDUCE_PREC_BITS; - const int offset_bits_horiz = - use_conv_params ? bd + FILTER_BITS - 1 : bd + WARPEDPIXEL_FILTER_BITS - 1; - const int offset_bits_vert = - use_conv_params - ? bd + 2 * FILTER_BITS - conv_params->round_0 - : bd + 2 * WARPEDPIXEL_FILTER_BITS - HORSHEAR_REDUCE_PREC_BITS; - if (use_conv_params) { - conv_params->do_post_rounding = 1; - } - assert(FILTER_BITS == WARPEDPIXEL_FILTER_BITS); -#else - const int reduce_bits_horiz = HORSHEAR_REDUCE_PREC_BITS; - const int max_bits_horiz = - bd + WARPEDPIXEL_FILTER_BITS + 1 - HORSHEAR_REDUCE_PREC_BITS; - const int offset_bits_horiz = bd + WARPEDPIXEL_FILTER_BITS - 1; - const int offset_bits_vert = - bd + 2 * WARPEDPIXEL_FILTER_BITS - HORSHEAR_REDUCE_PREC_BITS; -#endif + conv_params->round_0 + + AOMMAX(bd + FILTER_BITS - conv_params->round_0 - 14, 0); + const int reduce_bits_vert = conv_params->is_compound + ? conv_params->round_1 + : 2 * FILTER_BITS - reduce_bits_horiz; + const int max_bits_horiz = bd + FILTER_BITS + 1 - reduce_bits_horiz; + const int offset_bits_horiz = bd + FILTER_BITS - 1; + const int offset_bits_vert = bd + 2 * FILTER_BITS - reduce_bits_horiz; + const int round_bits = + 2 * FILTER_BITS - conv_params->round_0 - conv_params->round_1; + const int offset_bits = bd + 2 * FILTER_BITS - conv_params->round_0; (void)max_bits_horiz; + assert(IMPLIES(conv_params->is_compound, conv_params->dst != NULL)); - for (i = p_row; i < p_row + p_height; i += 8) { - for (j = p_col; j < p_col + p_width; j += 8) { + for (int i = p_row; i < p_row + p_height; i += 8) { + for (int j = p_col; j < p_col + p_width; j += 8) { // Calculate the center of this 8x8 block, // project to luma coordinates (if in a subsampled chroma plane), // apply the affine transformation, @@ -980,9 +453,9 @@ void av1_highbd_warp_affine_c(const int32_t *mat, const uint16_t *ref, const int32_t x4 = dst_x >> subsampling_x; const int32_t y4 = dst_y >> subsampling_y; - int32_t ix4 = x4 >> WARPEDMODEL_PREC_BITS; + const int32_t ix4 = x4 >> WARPEDMODEL_PREC_BITS; int32_t sx4 = x4 & ((1 << WARPEDMODEL_PREC_BITS) - 1); - int32_t iy4 = y4 >> WARPEDMODEL_PREC_BITS; + const int32_t iy4 = y4 >> WARPEDMODEL_PREC_BITS; int32_t sy4 = y4 & ((1 << WARPEDMODEL_PREC_BITS) - 1); sx4 += alpha * (-4) + beta * (-4); @@ -992,15 +465,11 @@ void av1_highbd_warp_affine_c(const int32_t *mat, const uint16_t *ref, sy4 &= ~((1 << WARP_PARAM_REDUCE_BITS) - 1); // Horizontal filter - for (k = -7; k < 8; ++k) { - int iy = iy4 + k; - if (iy < 0) - iy = 0; - else if (iy > height - 1) - iy = height - 1; + for (int k = -7; k < 8; ++k) { + const int iy = clamp(iy4 + k, 0, height - 1); int sx = sx4 + beta * (k + 4); - for (l = -4; l < 4; ++l) { + for (int l = -4; l < 4; ++l) { int ix = ix4 + l - 3; const int offs = ROUND_POWER_OF_TWO(sx, WARPEDDIFF_PREC_BITS) + WARPEDPIXEL_PREC_SHIFTS; @@ -1008,12 +477,8 @@ void av1_highbd_warp_affine_c(const int32_t *mat, const uint16_t *ref, const int16_t *coeffs = warped_filter[offs]; int32_t sum = 1 << offset_bits_horiz; - for (m = 0; m < 8; ++m) { - int sample_x = ix + m; - if (sample_x < 0) - sample_x = 0; - else if (sample_x > width - 1) - sample_x = width - 1; + for (int m = 0; m < 8; ++m) { + const int sample_x = clamp(ix + m, 0, width - 1); sum += ref[iy * stride + sample_x] * coeffs[m]; } sum = ROUND_POWER_OF_TWO(sum, reduce_bits_horiz); @@ -1024,46 +489,50 @@ void av1_highbd_warp_affine_c(const int32_t *mat, const uint16_t *ref, } // Vertical filter - for (k = -4; k < AOMMIN(4, p_row + p_height - i - 4); ++k) { + for (int k = -4; k < AOMMIN(4, p_row + p_height - i - 4); ++k) { int sy = sy4 + delta * (k + 4); - for (l = -4; l < AOMMIN(4, p_col + p_width - j - 4); ++l) { + for (int l = -4; l < AOMMIN(4, p_col + p_width - j - 4); ++l) { const int offs = ROUND_POWER_OF_TWO(sy, WARPEDDIFF_PREC_BITS) + WARPEDPIXEL_PREC_SHIFTS; assert(offs >= 0 && offs <= WARPEDPIXEL_PREC_SHIFTS * 3); const int16_t *coeffs = warped_filter[offs]; int32_t sum = 1 << offset_bits_vert; - for (m = 0; m < 8; ++m) { + for (int m = 0; m < 8; ++m) { sum += tmp[(k + m + 4) * 8 + (l + 4)] * coeffs[m]; } -#if CONFIG_CONVOLVE_ROUND - if (use_conv_params) { + + if (conv_params->is_compound) { CONV_BUF_TYPE *p = &conv_params ->dst[(i - p_row + k + 4) * conv_params->dst_stride + (j - p_col + l + 4)]; - sum = ROUND_POWER_OF_TWO(sum, conv_params->round_1) - - (1 << (offset_bits_horiz + FILTER_BITS - - conv_params->round_0 - conv_params->round_1)) - - (1 << (offset_bits_vert - conv_params->round_1)); - if (conv_params->do_average) - *p += sum; - else + sum = ROUND_POWER_OF_TWO(sum, reduce_bits_vert); + if (conv_params->do_average) { + uint16_t *dst16 = + &pred[(i - p_row + k + 4) * p_stride + (j - p_col + l + 4)]; + int32_t tmp32 = *p; + if (conv_params->use_jnt_comp_avg) { + tmp32 = tmp32 * conv_params->fwd_offset + + sum * conv_params->bck_offset; + tmp32 = tmp32 >> DIST_PRECISION_BITS; + } else { + tmp32 += sum; + tmp32 = tmp32 >> 1; + } + tmp32 = tmp32 - (1 << (offset_bits - conv_params->round_1)) - + (1 << (offset_bits - conv_params->round_1 - 1)); + *dst16 = + clip_pixel_highbd(ROUND_POWER_OF_TWO(tmp32, round_bits), bd); + } else { *p = sum; + } } else { -#else - { -#endif uint16_t *p = &pred[(i - p_row + k + 4) * p_stride + (j - p_col + l + 4)]; - sum = ROUND_POWER_OF_TWO(sum, VERSHEAR_REDUCE_PREC_BITS); + sum = ROUND_POWER_OF_TWO(sum, reduce_bits_vert); assert(0 <= sum && sum < (1 << (bd + 2))); - uint16_t px = - clip_pixel_highbd(sum - (1 << (bd - 1)) - (1 << bd), bd); - if (conv_params->do_average) - *p = ROUND_POWER_OF_TWO(*p + px, 1); - else - *p = px; + *p = clip_pixel_highbd(sum - (1 << (bd - 1)) - (1 << bd), bd); } sy += gamma; } @@ -1076,32 +545,25 @@ static void highbd_warp_plane(WarpedMotionParams *wm, const uint8_t *const ref8, int width, int height, int stride, const uint8_t *const pred8, int p_col, int p_row, int p_width, int p_height, int p_stride, - int subsampling_x, int subsampling_y, int x_scale, - int y_scale, int bd, + int subsampling_x, int subsampling_y, int bd, ConvolveParams *conv_params) { + assert(wm->wmtype <= AFFINE); if (wm->wmtype == ROTZOOM) { wm->wmmat[5] = wm->wmmat[2]; wm->wmmat[4] = -wm->wmmat[3]; } - if ((wm->wmtype == ROTZOOM || wm->wmtype == AFFINE) && - x_scale == SCALE_SUBPEL_SHIFTS && y_scale == SCALE_SUBPEL_SHIFTS) { - const int32_t *const mat = wm->wmmat; - const int16_t alpha = wm->alpha; - const int16_t beta = wm->beta; - const int16_t gamma = wm->gamma; - const int16_t delta = wm->delta; - - const uint16_t *const ref = CONVERT_TO_SHORTPTR(ref8); - uint16_t *pred = CONVERT_TO_SHORTPTR(pred8); - av1_highbd_warp_affine(mat, ref, width, height, stride, pred, p_col, p_row, - p_width, p_height, p_stride, subsampling_x, - subsampling_y, bd, conv_params, alpha, beta, gamma, - delta); - } else { - highbd_warp_plane_old(wm, ref8, width, height, stride, pred8, p_col, p_row, - p_width, p_height, p_stride, subsampling_x, - subsampling_y, x_scale, y_scale, bd, conv_params); - } + const int32_t *const mat = wm->wmmat; + const int16_t alpha = wm->alpha; + const int16_t beta = wm->beta; + const int16_t gamma = wm->gamma; + const int16_t delta = wm->delta; + + const uint16_t *const ref = CONVERT_TO_SHORTPTR(ref8); + uint16_t *pred = CONVERT_TO_SHORTPTR(pred8); + av1_highbd_warp_affine(mat, ref, width, height, stride, pred, p_col, p_row, + p_width, p_height, p_stride, subsampling_x, + subsampling_y, bd, conv_params, alpha, beta, gamma, + delta); } static int64_t highbd_frame_error(const uint16_t *const ref, int stride, @@ -1120,25 +582,25 @@ static int64_t highbd_frame_error(const uint16_t *const ref, int stride, static int64_t highbd_warp_error( WarpedMotionParams *wm, const uint8_t *const ref8, int width, int height, int stride, const uint8_t *const dst8, int p_col, int p_row, int p_width, - int p_height, int p_stride, int subsampling_x, int subsampling_y, - int x_scale, int y_scale, int bd, int64_t best_error) { + int p_height, int p_stride, int subsampling_x, int subsampling_y, int bd, + int64_t best_error) { int64_t gm_sumerr = 0; - int warp_w, warp_h; - int error_bsize_w = AOMMIN(p_width, WARP_ERROR_BLOCK); - int error_bsize_h = AOMMIN(p_height, WARP_ERROR_BLOCK); + const int error_bsize_w = AOMMIN(p_width, WARP_ERROR_BLOCK); + const int error_bsize_h = AOMMIN(p_height, WARP_ERROR_BLOCK); uint16_t tmp[WARP_ERROR_BLOCK * WARP_ERROR_BLOCK]; - ConvolveParams conv_params = get_conv_params(0, 0, 0); + ConvolveParams conv_params = get_conv_params(0, 0, 0, bd); + conv_params.use_jnt_comp_avg = 0; for (int i = p_row; i < p_row + p_height; i += WARP_ERROR_BLOCK) { for (int j = p_col; j < p_col + p_width; j += WARP_ERROR_BLOCK) { // avoid warping extra 8x8 blocks in the padded region of the frame // when p_width and p_height are not multiples of WARP_ERROR_BLOCK - warp_w = AOMMIN(error_bsize_w, p_col + p_width - j); - warp_h = AOMMIN(error_bsize_h, p_row + p_height - i); + const int warp_w = AOMMIN(error_bsize_w, p_col + p_width - j); + const int warp_h = AOMMIN(error_bsize_h, p_row + p_height - i); highbd_warp_plane(wm, ref8, width, height, stride, CONVERT_TO_BYTEPTR(tmp), j, i, warp_w, warp_h, - WARP_ERROR_BLOCK, subsampling_x, subsampling_y, x_scale, - y_scale, bd, &conv_params); + WARP_ERROR_BLOCK, subsampling_x, subsampling_y, bd, + &conv_params); gm_sumerr += highbd_frame_error( tmp, WARP_ERROR_BLOCK, CONVERT_TO_SHORTPTR(dst8) + j + i * p_stride, @@ -1148,41 +610,11 @@ static int64_t highbd_warp_error( } return gm_sumerr; } -#endif // CONFIG_HIGHBITDEPTH static INLINE int error_measure(int err) { return error_measure_lut[255 + err]; } -static void warp_plane_old(const WarpedMotionParams *const wm, - const uint8_t *const ref, int width, int height, - int stride, uint8_t *pred, int p_col, int p_row, - int p_width, int p_height, int p_stride, - int subsampling_x, int subsampling_y, int x_scale, - int y_scale, ConvolveParams *conv_params) { - int i, j; - ProjectPointsFunc projectpoints = get_project_points_type(wm->wmtype); - if (projectpoints == NULL) return; - for (i = p_row; i < p_row + p_height; ++i) { - for (j = p_col; j < p_col + p_width; ++j) { - int in[2], out[2]; - in[0] = j; - in[1] = i; - projectpoints(wm->wmmat, in, out, 1, 2, 2, subsampling_x, subsampling_y); - out[0] = ROUND_POWER_OF_TWO_SIGNED(out[0] * x_scale, SCALE_SUBPEL_BITS); - out[1] = ROUND_POWER_OF_TWO_SIGNED(out[1] * y_scale, SCALE_SUBPEL_BITS); - if (conv_params->do_average) - pred[(j - p_col) + (i - p_row) * p_stride] = ROUND_POWER_OF_TWO( - pred[(j - p_col) + (i - p_row) * p_stride] + - warp_interpolate(ref, out[0], out[1], width, height, stride), - 1); - else - pred[(j - p_col) + (i - p_row) * p_stride] = - warp_interpolate(ref, out[0], out[1], width, height, stride); - } - } -} - /* The warp filter for ROTZOOM and AFFINE models works as follows: * Split the input into 8x8 blocks * For each block, project the point (4, 4) within the block, to get the @@ -1237,10 +669,10 @@ static void warp_plane_old(const WarpedMotionParams *const wm, This allows the derivation of the appropriate bit widths and offsets for the various intermediate values: If - F := WARPEDPIXEL_FILTER_BITS = 7 (or else the above ranges need adjusting) + F := FILTER_BITS = 7 (or else the above ranges need adjusting) So a *single* filter stage maps a k-bit input to a (k + F + 1)-bit intermediate value. - H := HORSHEAR_REDUCE_PREC_BITS + H := ROUND0_BITS V := VERSHEAR_REDUCE_PREC_BITS (and note that we must have H + V = 2*F for the output to have the same scale as the input) @@ -1275,38 +707,23 @@ void av1_warp_affine_c(const int32_t *mat, const uint8_t *ref, int width, ConvolveParams *conv_params, int16_t alpha, int16_t beta, int16_t gamma, int16_t delta) { int32_t tmp[15 * 8]; - int i, j, k, l, m; const int bd = 8; -#if CONFIG_CONVOLVE_ROUND - const int use_conv_params = conv_params->round == CONVOLVE_OPT_NO_ROUND; - const int reduce_bits_horiz = - use_conv_params ? conv_params->round_0 : HORSHEAR_REDUCE_PREC_BITS; - const int max_bits_horiz = - use_conv_params - ? bd + FILTER_BITS + 1 - conv_params->round_0 - : bd + WARPEDPIXEL_FILTER_BITS + 1 - HORSHEAR_REDUCE_PREC_BITS; - const int offset_bits_horiz = - use_conv_params ? bd + FILTER_BITS - 1 : bd + WARPEDPIXEL_FILTER_BITS - 1; - const int offset_bits_vert = - use_conv_params - ? bd + 2 * FILTER_BITS - conv_params->round_0 - : bd + 2 * WARPEDPIXEL_FILTER_BITS - HORSHEAR_REDUCE_PREC_BITS; - if (use_conv_params) { - conv_params->do_post_rounding = 1; - } - assert(FILTER_BITS == WARPEDPIXEL_FILTER_BITS); -#else - const int reduce_bits_horiz = HORSHEAR_REDUCE_PREC_BITS; - const int max_bits_horiz = - bd + WARPEDPIXEL_FILTER_BITS + 1 - HORSHEAR_REDUCE_PREC_BITS; - const int offset_bits_horiz = bd + WARPEDPIXEL_FILTER_BITS - 1; - const int offset_bits_vert = - bd + 2 * WARPEDPIXEL_FILTER_BITS - HORSHEAR_REDUCE_PREC_BITS; -#endif + const int reduce_bits_horiz = conv_params->round_0; + const int reduce_bits_vert = conv_params->is_compound + ? conv_params->round_1 + : 2 * FILTER_BITS - reduce_bits_horiz; + const int max_bits_horiz = bd + FILTER_BITS + 1 - reduce_bits_horiz; + const int offset_bits_horiz = bd + FILTER_BITS - 1; + const int offset_bits_vert = bd + 2 * FILTER_BITS - reduce_bits_horiz; + const int round_bits = + 2 * FILTER_BITS - conv_params->round_0 - conv_params->round_1; + const int offset_bits = bd + 2 * FILTER_BITS - conv_params->round_0; (void)max_bits_horiz; + assert(IMPLIES(conv_params->is_compound, conv_params->dst != NULL)); + assert(IMPLIES(conv_params->do_average, conv_params->is_compound)); - for (i = p_row; i < p_row + p_height; i += 8) { - for (j = p_col; j < p_col + p_width; j += 8) { + for (int i = p_row; i < p_row + p_height; i += 8) { + for (int j = p_col; j < p_col + p_width; j += 8) { // Calculate the center of this 8x8 block, // project to luma coordinates (if in a subsampled chroma plane), // apply the affine transformation, @@ -1330,17 +747,13 @@ void av1_warp_affine_c(const int32_t *mat, const uint8_t *ref, int width, sy4 &= ~((1 << WARP_PARAM_REDUCE_BITS) - 1); // Horizontal filter - for (k = -7; k < 8; ++k) { + for (int k = -7; k < 8; ++k) { // Clamp to top/bottom edge of the frame - int iy = iy4 + k; - if (iy < 0) - iy = 0; - else if (iy > height - 1) - iy = height - 1; + const int iy = clamp(iy4 + k, 0, height - 1); int sx = sx4 + beta * (k + 4); - for (l = -4; l < 4; ++l) { + for (int l = -4; l < 4; ++l) { int ix = ix4 + l - 3; // At this point, sx = sx4 + alpha * l + beta * k const int offs = ROUND_POWER_OF_TWO(sx, WARPEDDIFF_PREC_BITS) + @@ -1349,13 +762,9 @@ void av1_warp_affine_c(const int32_t *mat, const uint8_t *ref, int width, const int16_t *coeffs = warped_filter[offs]; int32_t sum = 1 << offset_bits_horiz; - for (m = 0; m < 8; ++m) { + for (int m = 0; m < 8; ++m) { // Clamp to left/right edge of the frame - int sample_x = ix + m; - if (sample_x < 0) - sample_x = 0; - else if (sample_x > width - 1) - sample_x = width - 1; + const int sample_x = clamp(ix + m, 0, width - 1); sum += ref[iy * stride + sample_x] * coeffs[m]; } @@ -1367,9 +776,9 @@ void av1_warp_affine_c(const int32_t *mat, const uint8_t *ref, int width, } // Vertical filter - for (k = -4; k < AOMMIN(4, p_row + p_height - i - 4); ++k) { + for (int k = -4; k < AOMMIN(4, p_row + p_height - i - 4); ++k) { int sy = sy4 + delta * (k + 4); - for (l = -4; l < AOMMIN(4, p_col + p_width - j - 4); ++l) { + for (int l = -4; l < AOMMIN(4, p_col + p_width - j - 4); ++l) { // At this point, sy = sy4 + gamma * l + delta * k const int offs = ROUND_POWER_OF_TWO(sy, WARPEDDIFF_PREC_BITS) + WARPEDPIXEL_PREC_SHIFTS; @@ -1377,36 +786,40 @@ void av1_warp_affine_c(const int32_t *mat, const uint8_t *ref, int width, const int16_t *coeffs = warped_filter[offs]; int32_t sum = 1 << offset_bits_vert; - for (m = 0; m < 8; ++m) { + for (int m = 0; m < 8; ++m) { sum += tmp[(k + m + 4) * 8 + (l + 4)] * coeffs[m]; } -#if CONFIG_CONVOLVE_ROUND - if (use_conv_params) { + + if (conv_params->is_compound) { CONV_BUF_TYPE *p = &conv_params ->dst[(i - p_row + k + 4) * conv_params->dst_stride + (j - p_col + l + 4)]; - sum = ROUND_POWER_OF_TWO(sum, conv_params->round_1) - - (1 << (offset_bits_horiz + FILTER_BITS - - conv_params->round_0 - conv_params->round_1)) - - (1 << (offset_bits_vert - conv_params->round_1)); - if (conv_params->do_average) - *p += sum; - else + sum = ROUND_POWER_OF_TWO(sum, reduce_bits_vert); + if (conv_params->do_average) { + uint8_t *dst8 = + &pred[(i - p_row + k + 4) * p_stride + (j - p_col + l + 4)]; + int32_t tmp32 = *p; + if (conv_params->use_jnt_comp_avg) { + tmp32 = tmp32 * conv_params->fwd_offset + + sum * conv_params->bck_offset; + tmp32 = tmp32 >> DIST_PRECISION_BITS; + } else { + tmp32 += sum; + tmp32 = tmp32 >> 1; + } + tmp32 = tmp32 - (1 << (offset_bits - conv_params->round_1)) - + (1 << (offset_bits - conv_params->round_1 - 1)); + *dst8 = clip_pixel(ROUND_POWER_OF_TWO(tmp32, round_bits)); + } else { *p = sum; + } } else { -#else - { -#endif uint8_t *p = &pred[(i - p_row + k + 4) * p_stride + (j - p_col + l + 4)]; - sum = ROUND_POWER_OF_TWO(sum, VERSHEAR_REDUCE_PREC_BITS); + sum = ROUND_POWER_OF_TWO(sum, reduce_bits_vert); assert(0 <= sum && sum < (1 << (bd + 2))); - uint8_t px = clip_pixel(sum - (1 << (bd - 1)) - (1 << bd)); - if (conv_params->do_average) - *p = ROUND_POWER_OF_TWO(*p + px, 1); - else - *p = px; + *p = clip_pixel(sum - (1 << (bd - 1)) - (1 << bd)); } sy += gamma; } @@ -1419,27 +832,20 @@ static void warp_plane(WarpedMotionParams *wm, const uint8_t *const ref, int width, int height, int stride, uint8_t *pred, int p_col, int p_row, int p_width, int p_height, int p_stride, int subsampling_x, int subsampling_y, - int x_scale, int y_scale, ConvolveParams *conv_params) { + ConvolveParams *conv_params) { + assert(wm->wmtype <= AFFINE); if (wm->wmtype == ROTZOOM) { wm->wmmat[5] = wm->wmmat[2]; wm->wmmat[4] = -wm->wmmat[3]; } - if ((wm->wmtype == ROTZOOM || wm->wmtype == AFFINE) && - x_scale == SCALE_SUBPEL_SHIFTS && y_scale == SCALE_SUBPEL_SHIFTS) { - const int32_t *const mat = wm->wmmat; - const int16_t alpha = wm->alpha; - const int16_t beta = wm->beta; - const int16_t gamma = wm->gamma; - const int16_t delta = wm->delta; - - av1_warp_affine(mat, ref, width, height, stride, pred, p_col, p_row, - p_width, p_height, p_stride, subsampling_x, subsampling_y, - conv_params, alpha, beta, gamma, delta); - } else { - warp_plane_old(wm, ref, width, height, stride, pred, p_col, p_row, p_width, - p_height, p_stride, subsampling_x, subsampling_y, x_scale, - y_scale, conv_params); - } + const int32_t *const mat = wm->wmmat; + const int16_t alpha = wm->alpha; + const int16_t beta = wm->beta; + const int16_t gamma = wm->gamma; + const int16_t delta = wm->delta; + av1_warp_affine(mat, ref, width, height, stride, pred, p_col, p_row, p_width, + p_height, p_stride, subsampling_x, subsampling_y, conv_params, + alpha, beta, gamma, delta); } static int64_t frame_error(const uint8_t *const ref, int stride, @@ -1459,14 +865,15 @@ static int64_t warp_error(WarpedMotionParams *wm, const uint8_t *const ref, int width, int height, int stride, const uint8_t *const dst, int p_col, int p_row, int p_width, int p_height, int p_stride, - int subsampling_x, int subsampling_y, int x_scale, - int y_scale, int64_t best_error) { + int subsampling_x, int subsampling_y, + int64_t best_error) { int64_t gm_sumerr = 0; int warp_w, warp_h; int error_bsize_w = AOMMIN(p_width, WARP_ERROR_BLOCK); int error_bsize_h = AOMMIN(p_height, WARP_ERROR_BLOCK); uint8_t tmp[WARP_ERROR_BLOCK * WARP_ERROR_BLOCK]; - ConvolveParams conv_params = get_conv_params(0, 0, 0); + ConvolveParams conv_params = get_conv_params(0, 0, 0, 8); + conv_params.use_jnt_comp_avg = 0; for (int i = p_row; i < p_row + p_height; i += WARP_ERROR_BLOCK) { for (int j = p_col; j < p_col + p_width; j += WARP_ERROR_BLOCK) { @@ -1475,8 +882,7 @@ static int64_t warp_error(WarpedMotionParams *wm, const uint8_t *const ref, warp_w = AOMMIN(error_bsize_w, p_col + p_width - j); warp_h = AOMMIN(error_bsize_h, p_row + p_height - i); warp_plane(wm, ref, width, height, stride, tmp, j, i, warp_w, warp_h, - WARP_ERROR_BLOCK, subsampling_x, subsampling_y, x_scale, - y_scale, &conv_params); + WARP_ERROR_BLOCK, subsampling_x, subsampling_y, &conv_params); gm_sumerr += frame_error(tmp, WARP_ERROR_BLOCK, dst + j + i * p_stride, warp_w, warp_h, p_stride); @@ -1486,70 +892,49 @@ static int64_t warp_error(WarpedMotionParams *wm, const uint8_t *const ref, return gm_sumerr; } -int64_t av1_frame_error( -#if CONFIG_HIGHBITDEPTH - int use_hbd, int bd, -#endif // CONFIG_HIGHBITDEPTH - const uint8_t *ref, int stride, uint8_t *dst, int p_width, int p_height, - int p_stride) { -#if CONFIG_HIGHBITDEPTH +int64_t av1_frame_error(int use_hbd, int bd, const uint8_t *ref, int stride, + uint8_t *dst, int p_width, int p_height, int p_stride) { if (use_hbd) { return highbd_frame_error(CONVERT_TO_SHORTPTR(ref), stride, CONVERT_TO_SHORTPTR(dst), p_width, p_height, p_stride, bd); } -#endif // CONFIG_HIGHBITDEPTH return frame_error(ref, stride, dst, p_width, p_height, p_stride); } -int64_t av1_warp_error(WarpedMotionParams *wm, -#if CONFIG_HIGHBITDEPTH - int use_hbd, int bd, -#endif // CONFIG_HIGHBITDEPTH +int64_t av1_warp_error(WarpedMotionParams *wm, int use_hbd, int bd, const uint8_t *ref, int width, int height, int stride, uint8_t *dst, int p_col, int p_row, int p_width, int p_height, int p_stride, int subsampling_x, - int subsampling_y, int x_scale, int y_scale, - int64_t best_error) { + int subsampling_y, int64_t best_error) { if (wm->wmtype <= AFFINE) if (!get_shear_params(wm)) return 1; -#if CONFIG_HIGHBITDEPTH if (use_hbd) return highbd_warp_error(wm, ref, width, height, stride, dst, p_col, p_row, p_width, p_height, p_stride, subsampling_x, - subsampling_y, x_scale, y_scale, bd, best_error); -#endif // CONFIG_HIGHBITDEPTH + subsampling_y, bd, best_error); return warp_error(wm, ref, width, height, stride, dst, p_col, p_row, p_width, - p_height, p_stride, subsampling_x, subsampling_y, x_scale, - y_scale, best_error); + p_height, p_stride, subsampling_x, subsampling_y, + best_error); } -void av1_warp_plane(WarpedMotionParams *wm, -#if CONFIG_HIGHBITDEPTH - int use_hbd, int bd, -#endif // CONFIG_HIGHBITDEPTH +void av1_warp_plane(WarpedMotionParams *wm, int use_hbd, int bd, const uint8_t *ref, int width, int height, int stride, uint8_t *pred, int p_col, int p_row, int p_width, int p_height, int p_stride, int subsampling_x, - int subsampling_y, int x_scale, int y_scale, - ConvolveParams *conv_params) { -#if CONFIG_HIGHBITDEPTH + int subsampling_y, ConvolveParams *conv_params) { if (use_hbd) highbd_warp_plane(wm, ref, width, height, stride, pred, p_col, p_row, p_width, p_height, p_stride, subsampling_x, subsampling_y, - x_scale, y_scale, bd, conv_params); + bd, conv_params); else -#endif // CONFIG_HIGHBITDEPTH warp_plane(wm, ref, width, height, stride, pred, p_col, p_row, p_width, - p_height, p_stride, subsampling_x, subsampling_y, x_scale, - y_scale, conv_params); + p_height, p_stride, subsampling_x, subsampling_y, conv_params); } -#if CONFIG_WARPED_MOTION -#define LEAST_SQUARES_ORDER 2 - #define LS_MV_MAX 256 // max mv in 1/8-pel -#define LS_STEP 2 +// Use LS_STEP = 8 so that 2 less bits needed for A, Bx, By. +#define LS_STEP 8 // Assuming LS_MV_MAX is < MAX_SB_SIZE * 8, // the precision needed is: @@ -1570,13 +955,17 @@ void av1_warp_plane(WarpedMotionParams *wm, #define LS_MAT_MIN (-(1 << (LS_MAT_BITS - 1))) #define LS_MAT_MAX ((1 << (LS_MAT_BITS - 1)) - 1) -#define LS_SUM(a) ((a)*4 + LS_STEP * 2) -#define LS_SQUARE(a) \ - (((a) * (a)*4 + (a)*4 * LS_STEP + LS_STEP * LS_STEP * 2) >> 2) -#define LS_PRODUCT1(a, b) \ - (((a) * (b)*4 + ((a) + (b)) * 2 * LS_STEP + LS_STEP * LS_STEP) >> 2) -#define LS_PRODUCT2(a, b) \ - (((a) * (b)*4 + ((a) + (b)) * 2 * LS_STEP + LS_STEP * LS_STEP * 2) >> 2) +// By setting LS_STEP = 8, the least 2 bits of every elements in A, Bx, By are +// 0. So, we can reduce LS_MAT_RANGE_BITS(2) bits here. +#define LS_SQUARE(a) \ + (((a) * (a)*4 + (a)*4 * LS_STEP + LS_STEP * LS_STEP * 2) >> \ + (2 + LS_MAT_DOWN_BITS)) +#define LS_PRODUCT1(a, b) \ + (((a) * (b)*4 + ((a) + (b)) * 2 * LS_STEP + LS_STEP * LS_STEP) >> \ + (2 + LS_MAT_DOWN_BITS)) +#define LS_PRODUCT2(a, b) \ + (((a) * (b)*4 + ((a) + (b)) * 2 * LS_STEP + LS_STEP * LS_STEP * 2) >> \ + (2 + LS_MAT_DOWN_BITS)) #define USE_LIMITED_PREC_MULT 0 @@ -1655,22 +1044,24 @@ static int32_t get_mult_shift_diag(int64_t Px, int16_t iDet, int shift) { } #endif // USE_LIMITED_PREC_MULT -static int find_affine_int(int np, int *pts1, int *pts2, BLOCK_SIZE bsize, - int mvy, int mvx, WarpedMotionParams *wm, int mi_row, - int mi_col) { +static int find_affine_int(int np, const int *pts1, const int *pts2, + BLOCK_SIZE bsize, int mvy, int mvx, + WarpedMotionParams *wm, int mi_row, int mi_col) { int32_t A[2][2] = { { 0, 0 }, { 0, 0 } }; int32_t Bx[2] = { 0, 0 }; int32_t By[2] = { 0, 0 }; - int i, n = 0; + int i; const int bw = block_size_wide[bsize]; const int bh = block_size_high[bsize]; - const int isuy = (mi_row * MI_SIZE + AOMMAX(bh, MI_SIZE) / 2 - 1); - const int isux = (mi_col * MI_SIZE + AOMMAX(bw, MI_SIZE) / 2 - 1); - const int suy = isuy * 8; - const int sux = isux * 8; + const int rsuy = (AOMMAX(bh, MI_SIZE) / 2 - 1); + const int rsux = (AOMMAX(bw, MI_SIZE) / 2 - 1); + const int suy = rsuy * 8; + const int sux = rsux * 8; const int duy = suy + mvy; const int dux = sux + mvx; + const int isuy = (mi_row * MI_SIZE + rsuy); + const int isux = (mi_col * MI_SIZE + rsux); // Assume the center pixel of the block has exactly the same motion vector // as transmitted for the block. First shift the origin of the source @@ -1694,13 +1085,15 @@ static int find_affine_int(int np, int *pts1, int *pts2, BLOCK_SIZE bsize, // // The loop below computes: A = P'P, Bx = P'q, By = P'r // We need to just compute inv(A).Bx and inv(A).By for the solutions. - int sx, sy, dx, dy; // Contribution from neighbor block - for (i = 0; i < np && n < LEAST_SQUARES_SAMPLES_MAX; i++) { - dx = pts2[i * 2] - dux; - dy = pts2[i * 2 + 1] - duy; - sx = pts1[i * 2] - sux; - sy = pts1[i * 2 + 1] - suy; + for (i = 0; i < np; i++) { + const int dx = pts2[i * 2] - dux; + const int dy = pts2[i * 2 + 1] - duy; + const int sx = pts1[i * 2] - sux; + const int sy = pts1[i * 2 + 1] - suy; + // (TODO)yunqing: This comparison wouldn't be necessary if the sample + // selection is done in find_samples(). Also, global offset can be removed + // while collecting samples. if (abs(sx - dx) < LS_MV_MAX && abs(sy - dy) < LS_MV_MAX) { A[0][0] += LS_SQUARE(sx); A[0][1] += LS_PRODUCT1(sx, sy); @@ -1709,41 +1102,20 @@ static int find_affine_int(int np, int *pts1, int *pts2, BLOCK_SIZE bsize, Bx[1] += LS_PRODUCT1(sy, dx); By[0] += LS_PRODUCT1(sx, dy); By[1] += LS_PRODUCT2(sy, dy); - n++; } } - int downshift; - if (n >= 4) - downshift = LS_MAT_DOWN_BITS; - else if (n >= 2) - downshift = LS_MAT_DOWN_BITS - 1; - else - downshift = LS_MAT_DOWN_BITS - 2; - - // Reduce precision by downshift bits - A[0][0] = clamp(ROUND_POWER_OF_TWO_SIGNED(A[0][0], downshift), LS_MAT_MIN, - LS_MAT_MAX); - A[0][1] = clamp(ROUND_POWER_OF_TWO_SIGNED(A[0][1], downshift), LS_MAT_MIN, - LS_MAT_MAX); - A[1][1] = clamp(ROUND_POWER_OF_TWO_SIGNED(A[1][1], downshift), LS_MAT_MIN, - LS_MAT_MAX); - Bx[0] = clamp(ROUND_POWER_OF_TWO_SIGNED(Bx[0], downshift), LS_MAT_MIN, - LS_MAT_MAX); - Bx[1] = clamp(ROUND_POWER_OF_TWO_SIGNED(Bx[1], downshift), LS_MAT_MIN, - LS_MAT_MAX); - By[0] = clamp(ROUND_POWER_OF_TWO_SIGNED(By[0], downshift), LS_MAT_MIN, - LS_MAT_MAX); - By[1] = clamp(ROUND_POWER_OF_TWO_SIGNED(By[1], downshift), LS_MAT_MIN, - LS_MAT_MAX); - - int64_t Px[2], Py[2], Det; - int16_t iDet, shift; - // These divided by the Det, are the least squares solutions - Px[0] = (int64_t)A[1][1] * Bx[0] - (int64_t)A[0][1] * Bx[1]; - Px[1] = -(int64_t)A[0][1] * Bx[0] + (int64_t)A[0][0] * Bx[1]; - Py[0] = (int64_t)A[1][1] * By[0] - (int64_t)A[0][1] * By[1]; - Py[1] = -(int64_t)A[0][1] * By[0] + (int64_t)A[0][0] * By[1]; + // Just for debugging, and can be removed later. + assert(A[0][0] >= LS_MAT_MIN && A[0][0] <= LS_MAT_MAX); + assert(A[0][1] >= LS_MAT_MIN && A[0][1] <= LS_MAT_MAX); + assert(A[1][1] >= LS_MAT_MIN && A[1][1] <= LS_MAT_MAX); + assert(Bx[0] >= LS_MAT_MIN && Bx[0] <= LS_MAT_MAX); + assert(Bx[1] >= LS_MAT_MIN && Bx[1] <= LS_MAT_MAX); + assert(By[0] >= LS_MAT_MIN && By[0] <= LS_MAT_MAX); + assert(By[1] >= LS_MAT_MIN && By[1] <= LS_MAT_MAX); + + int64_t Det; + int16_t iDet, shift; // Compute Determinant of A Det = (int64_t)A[0][0] * A[1][1] - (int64_t)A[0][1] * A[0][1]; @@ -1755,6 +1127,14 @@ static int find_affine_int(int np, int *pts1, int *pts2, BLOCK_SIZE bsize, shift = 0; } + int64_t Px[2], Py[2]; + + // These divided by the Det, are the least squares solutions + Px[0] = (int64_t)A[1][1] * Bx[0] - (int64_t)A[0][1] * Bx[1]; + Px[1] = -(int64_t)A[0][1] * Bx[0] + (int64_t)A[0][0] * Bx[1]; + Py[0] = (int64_t)A[1][1] * By[0] - (int64_t)A[0][1] * By[1]; + Py[1] = -(int64_t)A[0][1] * By[0] + (int64_t)A[0][0] * By[1]; + wm->wmmat[2] = get_mult_shift_diag(Px[0], iDet, shift); wm->wmmat[3] = get_mult_shift_ndiag(Px[1], iDet, shift); wm->wmmat[4] = get_mult_shift_ndiag(Py[0], iDet, shift); @@ -1783,13 +1163,13 @@ int find_projection(int np, int *pts1, int *pts2, BLOCK_SIZE bsize, int mvy, int mvx, WarpedMotionParams *wm_params, int mi_row, int mi_col) { assert(wm_params->wmtype == AFFINE); - const int result = find_affine_int(np, pts1, pts2, bsize, mvy, mvx, wm_params, - mi_row, mi_col); - if (result == 0) { - // check compatibility with the fast warp filter - if (!get_shear_params(wm_params)) return 1; - } - return result; + if (find_affine_int(np, pts1, pts2, bsize, mvy, mvx, wm_params, mi_row, + mi_col)) + return 1; + + // check compatibility with the fast warp filter + if (!get_shear_params(wm_params)) return 1; + + return 0; } -#endif // CONFIG_WARPED_MOTION |