Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 1 | /* |
Yaowu Xu | 2ab7ff0 | 2016-09-02 12:04:54 -0700 | [diff] [blame] | 2 | * Copyright (c) 2016, Alliance for Open Media. All rights reserved |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 3 | * |
Yaowu Xu | 2ab7ff0 | 2016-09-02 12:04:54 -0700 | [diff] [blame] | 4 | * This source code is subject to the terms of the BSD 2 Clause License and |
| 5 | * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
| 6 | * was not distributed with this source code in the LICENSE file, you can |
| 7 | * obtain it at www.aomedia.org/license/software. If the Alliance for Open |
| 8 | * Media Patent License 1.0 was not distributed with this source code in the |
| 9 | * PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 10 | */ |
| 11 | |
| 12 | #include <assert.h> |
| 13 | #include <limits.h> |
| 14 | #include <math.h> |
| 15 | #include <stdio.h> |
| 16 | #include <stdlib.h> |
| 17 | #include <string.h> |
| 18 | |
Alex Converse | 64d7ef6 | 2017-03-22 18:09:16 -0700 | [diff] [blame] | 19 | #include "./aom_config.h" |
Sebastien Alaiwan | 71e8784 | 2017-04-12 16:03:28 +0200 | [diff] [blame] | 20 | #if CONFIG_HIGHBITDEPTH |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 21 | #include "aom_dsp/aom_dsp_common.h" |
Sebastien Alaiwan | 71e8784 | 2017-04-12 16:03:28 +0200 | [diff] [blame] | 22 | #endif // CONFIG_HIGHBITDEPTH |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 23 | #include "aom_ports/mem.h" |
Fergus Simpson | 090bb60 | 2017-04-07 12:37:53 -0700 | [diff] [blame] | 24 | #include "aom_scale/aom_scale.h" |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 25 | #include "av1/common/common.h" |
Fergus Simpson | d056500 | 2017-03-27 16:51:52 -0700 | [diff] [blame] | 26 | #include "av1/common/resize.h" |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 27 | |
Fergus Simpson | 090bb60 | 2017-04-07 12:37:53 -0700 | [diff] [blame] | 28 | #include "./aom_scale_rtcd.h" |
| 29 | |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 30 | #define FILTER_BITS 7 |
| 31 | |
| 32 | #define INTERP_TAPS 8 |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 33 | #define SUBPEL_BITS_RS 6 |
Fergus Simpson | 090bb60 | 2017-04-07 12:37:53 -0700 | [diff] [blame] | 34 | #define SUBPEL_MASK_RS ((1 << SUBPEL_BITS_RS) - 1) |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 35 | #define INTERP_PRECISION_BITS 16 |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 36 | #define SUBPEL_INTERP_EXTRA_BITS (INTERP_PRECISION_BITS - SUBPEL_BITS_RS) |
| 37 | #define SUBPEL_INTERP_EXTRA_OFF (1 << (SUBPEL_INTERP_EXTRA_BITS - 1)) |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 38 | |
| 39 | typedef int16_t interp_kernel[INTERP_TAPS]; |
| 40 | |
| 41 | // Filters for interpolation (0.5-band) - note this also filters integer pels. |
Fergus Simpson | 090bb60 | 2017-04-07 12:37:53 -0700 | [diff] [blame] | 42 | static const interp_kernel filteredinterp_filters500[(1 << SUBPEL_BITS_RS)] = { |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 43 | { -3, 0, 35, 64, 35, 0, -3, 0 }, { -3, 0, 34, 64, 36, 0, -3, 0 }, |
| 44 | { -3, -1, 34, 64, 36, 1, -3, 0 }, { -3, -1, 33, 64, 37, 1, -3, 0 }, |
| 45 | { -3, -1, 32, 64, 38, 1, -3, 0 }, { -3, -1, 31, 64, 39, 1, -3, 0 }, |
| 46 | { -3, -1, 31, 63, 39, 2, -3, 0 }, { -2, -2, 30, 63, 40, 2, -3, 0 }, |
| 47 | { -2, -2, 29, 63, 41, 2, -3, 0 }, { -2, -2, 29, 63, 41, 3, -4, 0 }, |
| 48 | { -2, -2, 28, 63, 42, 3, -4, 0 }, { -2, -2, 27, 63, 43, 3, -4, 0 }, |
| 49 | { -2, -3, 27, 63, 43, 4, -4, 0 }, { -2, -3, 26, 62, 44, 5, -4, 0 }, |
| 50 | { -2, -3, 25, 62, 45, 5, -4, 0 }, { -2, -3, 25, 62, 45, 5, -4, 0 }, |
| 51 | { -2, -3, 24, 62, 46, 5, -4, 0 }, { -2, -3, 23, 61, 47, 6, -4, 0 }, |
| 52 | { -2, -3, 23, 61, 47, 6, -4, 0 }, { -2, -3, 22, 61, 48, 7, -4, -1 }, |
| 53 | { -2, -3, 21, 60, 49, 7, -4, 0 }, { -1, -4, 20, 60, 49, 8, -4, 0 }, |
| 54 | { -1, -4, 20, 60, 50, 8, -4, -1 }, { -1, -4, 19, 59, 51, 9, -4, -1 }, |
| 55 | { -1, -4, 19, 59, 51, 9, -4, -1 }, { -1, -4, 18, 58, 52, 10, -4, -1 }, |
| 56 | { -1, -4, 17, 58, 52, 11, -4, -1 }, { -1, -4, 16, 58, 53, 11, -4, -1 }, |
| 57 | { -1, -4, 16, 57, 53, 12, -4, -1 }, { -1, -4, 15, 57, 54, 12, -4, -1 }, |
| 58 | { -1, -4, 15, 56, 54, 13, -4, -1 }, { -1, -4, 14, 56, 55, 13, -4, -1 }, |
| 59 | { -1, -4, 14, 55, 55, 14, -4, -1 }, { -1, -4, 13, 55, 56, 14, -4, -1 }, |
| 60 | { -1, -4, 13, 54, 56, 15, -4, -1 }, { -1, -4, 12, 54, 57, 15, -4, -1 }, |
| 61 | { -1, -4, 12, 53, 57, 16, -4, -1 }, { -1, -4, 11, 53, 58, 16, -4, -1 }, |
| 62 | { -1, -4, 11, 52, 58, 17, -4, -1 }, { -1, -4, 10, 52, 58, 18, -4, -1 }, |
| 63 | { -1, -4, 9, 51, 59, 19, -4, -1 }, { -1, -4, 9, 51, 59, 19, -4, -1 }, |
| 64 | { -1, -4, 8, 50, 60, 20, -4, -1 }, { 0, -4, 8, 49, 60, 20, -4, -1 }, |
| 65 | { 0, -4, 7, 49, 60, 21, -3, -2 }, { -1, -4, 7, 48, 61, 22, -3, -2 }, |
| 66 | { 0, -4, 6, 47, 61, 23, -3, -2 }, { 0, -4, 6, 47, 61, 23, -3, -2 }, |
| 67 | { 0, -4, 5, 46, 62, 24, -3, -2 }, { 0, -4, 5, 45, 62, 25, -3, -2 }, |
| 68 | { 0, -4, 5, 45, 62, 25, -3, -2 }, { 0, -4, 5, 44, 62, 26, -3, -2 }, |
| 69 | { 0, -4, 4, 43, 63, 27, -3, -2 }, { 0, -4, 3, 43, 63, 27, -2, -2 }, |
| 70 | { 0, -4, 3, 42, 63, 28, -2, -2 }, { 0, -4, 3, 41, 63, 29, -2, -2 }, |
| 71 | { 0, -3, 2, 41, 63, 29, -2, -2 }, { 0, -3, 2, 40, 63, 30, -2, -2 }, |
| 72 | { 0, -3, 2, 39, 63, 31, -1, -3 }, { 0, -3, 1, 39, 64, 31, -1, -3 }, |
| 73 | { 0, -3, 1, 38, 64, 32, -1, -3 }, { 0, -3, 1, 37, 64, 33, -1, -3 }, |
| 74 | { 0, -3, 1, 36, 64, 34, -1, -3 }, { 0, -3, 0, 36, 64, 34, 0, -3 }, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 75 | }; |
| 76 | |
| 77 | // Filters for interpolation (0.625-band) - note this also filters integer pels. |
Fergus Simpson | 090bb60 | 2017-04-07 12:37:53 -0700 | [diff] [blame] | 78 | static const interp_kernel filteredinterp_filters625[(1 << SUBPEL_BITS_RS)] = { |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 79 | { -1, -8, 33, 80, 33, -8, -1, 0 }, { -1, -8, 31, 80, 34, -8, -1, 1 }, |
| 80 | { -1, -8, 30, 80, 35, -8, -1, 1 }, { -1, -8, 29, 80, 36, -7, -2, 1 }, |
| 81 | { -1, -8, 28, 80, 37, -7, -2, 1 }, { -1, -8, 27, 80, 38, -7, -2, 1 }, |
| 82 | { 0, -8, 26, 79, 39, -7, -2, 1 }, { 0, -8, 25, 79, 40, -7, -2, 1 }, |
| 83 | { 0, -8, 24, 79, 41, -7, -2, 1 }, { 0, -8, 23, 78, 42, -6, -2, 1 }, |
| 84 | { 0, -8, 22, 78, 43, -6, -2, 1 }, { 0, -8, 21, 78, 44, -6, -2, 1 }, |
| 85 | { 0, -8, 20, 78, 45, -5, -3, 1 }, { 0, -8, 19, 77, 47, -5, -3, 1 }, |
| 86 | { 0, -8, 18, 77, 48, -5, -3, 1 }, { 0, -8, 17, 77, 49, -5, -3, 1 }, |
| 87 | { 0, -8, 16, 76, 50, -4, -3, 1 }, { 0, -8, 15, 76, 51, -4, -3, 1 }, |
| 88 | { 0, -8, 15, 75, 52, -3, -4, 1 }, { 0, -7, 14, 74, 53, -3, -4, 1 }, |
| 89 | { 0, -7, 13, 74, 54, -3, -4, 1 }, { 0, -7, 12, 73, 55, -2, -4, 1 }, |
| 90 | { 0, -7, 11, 73, 56, -2, -4, 1 }, { 0, -7, 10, 72, 57, -1, -4, 1 }, |
| 91 | { 1, -7, 10, 71, 58, -1, -5, 1 }, { 0, -7, 9, 71, 59, 0, -5, 1 }, |
| 92 | { 1, -7, 8, 70, 60, 0, -5, 1 }, { 1, -7, 7, 69, 61, 1, -5, 1 }, |
| 93 | { 1, -6, 6, 68, 62, 1, -5, 1 }, { 0, -6, 6, 68, 62, 2, -5, 1 }, |
| 94 | { 1, -6, 5, 67, 63, 2, -5, 1 }, { 1, -6, 5, 66, 64, 3, -6, 1 }, |
| 95 | { 1, -6, 4, 65, 65, 4, -6, 1 }, { 1, -6, 3, 64, 66, 5, -6, 1 }, |
| 96 | { 1, -5, 2, 63, 67, 5, -6, 1 }, { 1, -5, 2, 62, 68, 6, -6, 0 }, |
| 97 | { 1, -5, 1, 62, 68, 6, -6, 1 }, { 1, -5, 1, 61, 69, 7, -7, 1 }, |
| 98 | { 1, -5, 0, 60, 70, 8, -7, 1 }, { 1, -5, 0, 59, 71, 9, -7, 0 }, |
| 99 | { 1, -5, -1, 58, 71, 10, -7, 1 }, { 1, -4, -1, 57, 72, 10, -7, 0 }, |
| 100 | { 1, -4, -2, 56, 73, 11, -7, 0 }, { 1, -4, -2, 55, 73, 12, -7, 0 }, |
| 101 | { 1, -4, -3, 54, 74, 13, -7, 0 }, { 1, -4, -3, 53, 74, 14, -7, 0 }, |
| 102 | { 1, -4, -3, 52, 75, 15, -8, 0 }, { 1, -3, -4, 51, 76, 15, -8, 0 }, |
| 103 | { 1, -3, -4, 50, 76, 16, -8, 0 }, { 1, -3, -5, 49, 77, 17, -8, 0 }, |
| 104 | { 1, -3, -5, 48, 77, 18, -8, 0 }, { 1, -3, -5, 47, 77, 19, -8, 0 }, |
| 105 | { 1, -3, -5, 45, 78, 20, -8, 0 }, { 1, -2, -6, 44, 78, 21, -8, 0 }, |
| 106 | { 1, -2, -6, 43, 78, 22, -8, 0 }, { 1, -2, -6, 42, 78, 23, -8, 0 }, |
| 107 | { 1, -2, -7, 41, 79, 24, -8, 0 }, { 1, -2, -7, 40, 79, 25, -8, 0 }, |
| 108 | { 1, -2, -7, 39, 79, 26, -8, 0 }, { 1, -2, -7, 38, 80, 27, -8, -1 }, |
| 109 | { 1, -2, -7, 37, 80, 28, -8, -1 }, { 1, -2, -7, 36, 80, 29, -8, -1 }, |
| 110 | { 1, -1, -8, 35, 80, 30, -8, -1 }, { 1, -1, -8, 34, 80, 31, -8, -1 }, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 111 | }; |
| 112 | |
| 113 | // Filters for interpolation (0.75-band) - note this also filters integer pels. |
Fergus Simpson | 090bb60 | 2017-04-07 12:37:53 -0700 | [diff] [blame] | 114 | static const interp_kernel filteredinterp_filters750[(1 << SUBPEL_BITS_RS)] = { |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 115 | { 2, -11, 25, 96, 25, -11, 2, 0 }, { 2, -11, 24, 96, 26, -11, 2, 0 }, |
| 116 | { 2, -11, 22, 96, 28, -11, 2, 0 }, { 2, -10, 21, 96, 29, -12, 2, 0 }, |
| 117 | { 2, -10, 19, 96, 31, -12, 2, 0 }, { 2, -10, 18, 95, 32, -11, 2, 0 }, |
| 118 | { 2, -10, 17, 95, 34, -12, 2, 0 }, { 2, -9, 15, 95, 35, -12, 2, 0 }, |
| 119 | { 2, -9, 14, 94, 37, -12, 2, 0 }, { 2, -9, 13, 94, 38, -12, 2, 0 }, |
| 120 | { 2, -8, 12, 93, 40, -12, 1, 0 }, { 2, -8, 11, 93, 41, -12, 1, 0 }, |
| 121 | { 2, -8, 9, 92, 43, -12, 1, 1 }, { 2, -8, 8, 92, 44, -12, 1, 1 }, |
| 122 | { 2, -7, 7, 91, 46, -12, 1, 0 }, { 2, -7, 6, 90, 47, -12, 1, 1 }, |
| 123 | { 2, -7, 5, 90, 49, -12, 1, 0 }, { 2, -6, 4, 89, 50, -12, 1, 0 }, |
| 124 | { 2, -6, 3, 88, 52, -12, 0, 1 }, { 2, -6, 2, 87, 54, -12, 0, 1 }, |
| 125 | { 2, -5, 1, 86, 55, -12, 0, 1 }, { 2, -5, 0, 85, 57, -12, 0, 1 }, |
| 126 | { 2, -5, -1, 84, 58, -11, 0, 1 }, { 2, -5, -2, 83, 60, -11, 0, 1 }, |
| 127 | { 2, -4, -2, 82, 61, -11, -1, 1 }, { 1, -4, -3, 81, 63, -10, -1, 1 }, |
| 128 | { 2, -4, -4, 80, 64, -10, -1, 1 }, { 1, -4, -4, 79, 66, -10, -1, 1 }, |
| 129 | { 1, -3, -5, 77, 67, -9, -1, 1 }, { 1, -3, -6, 76, 69, -9, -1, 1 }, |
| 130 | { 1, -3, -6, 75, 70, -8, -2, 1 }, { 1, -2, -7, 74, 71, -8, -2, 1 }, |
| 131 | { 1, -2, -7, 72, 72, -7, -2, 1 }, { 1, -2, -8, 71, 74, -7, -2, 1 }, |
| 132 | { 1, -2, -8, 70, 75, -6, -3, 1 }, { 1, -1, -9, 69, 76, -6, -3, 1 }, |
| 133 | { 1, -1, -9, 67, 77, -5, -3, 1 }, { 1, -1, -10, 66, 79, -4, -4, 1 }, |
| 134 | { 1, -1, -10, 64, 80, -4, -4, 2 }, { 1, -1, -10, 63, 81, -3, -4, 1 }, |
| 135 | { 1, -1, -11, 61, 82, -2, -4, 2 }, { 1, 0, -11, 60, 83, -2, -5, 2 }, |
| 136 | { 1, 0, -11, 58, 84, -1, -5, 2 }, { 1, 0, -12, 57, 85, 0, -5, 2 }, |
| 137 | { 1, 0, -12, 55, 86, 1, -5, 2 }, { 1, 0, -12, 54, 87, 2, -6, 2 }, |
| 138 | { 1, 0, -12, 52, 88, 3, -6, 2 }, { 0, 1, -12, 50, 89, 4, -6, 2 }, |
| 139 | { 0, 1, -12, 49, 90, 5, -7, 2 }, { 1, 1, -12, 47, 90, 6, -7, 2 }, |
| 140 | { 0, 1, -12, 46, 91, 7, -7, 2 }, { 1, 1, -12, 44, 92, 8, -8, 2 }, |
| 141 | { 1, 1, -12, 43, 92, 9, -8, 2 }, { 0, 1, -12, 41, 93, 11, -8, 2 }, |
| 142 | { 0, 1, -12, 40, 93, 12, -8, 2 }, { 0, 2, -12, 38, 94, 13, -9, 2 }, |
| 143 | { 0, 2, -12, 37, 94, 14, -9, 2 }, { 0, 2, -12, 35, 95, 15, -9, 2 }, |
| 144 | { 0, 2, -12, 34, 95, 17, -10, 2 }, { 0, 2, -11, 32, 95, 18, -10, 2 }, |
| 145 | { 0, 2, -12, 31, 96, 19, -10, 2 }, { 0, 2, -12, 29, 96, 21, -10, 2 }, |
| 146 | { 0, 2, -11, 28, 96, 22, -11, 2 }, { 0, 2, -11, 26, 96, 24, -11, 2 }, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 147 | }; |
| 148 | |
| 149 | // Filters for interpolation (0.875-band) - note this also filters integer pels. |
Fergus Simpson | 090bb60 | 2017-04-07 12:37:53 -0700 | [diff] [blame] | 150 | static const interp_kernel filteredinterp_filters875[(1 << SUBPEL_BITS_RS)] = { |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 151 | { 3, -8, 13, 112, 13, -8, 3, 0 }, { 2, -7, 12, 112, 15, -8, 3, -1 }, |
| 152 | { 3, -7, 10, 112, 17, -9, 3, -1 }, { 2, -6, 8, 112, 19, -9, 3, -1 }, |
| 153 | { 2, -6, 7, 112, 21, -10, 3, -1 }, { 2, -5, 6, 111, 22, -10, 3, -1 }, |
| 154 | { 2, -5, 4, 111, 24, -10, 3, -1 }, { 2, -4, 3, 110, 26, -11, 3, -1 }, |
| 155 | { 2, -4, 1, 110, 28, -11, 3, -1 }, { 2, -4, 0, 109, 30, -12, 4, -1 }, |
| 156 | { 1, -3, -1, 108, 32, -12, 4, -1 }, { 1, -3, -2, 108, 34, -13, 4, -1 }, |
| 157 | { 1, -2, -4, 107, 36, -13, 4, -1 }, { 1, -2, -5, 106, 38, -13, 4, -1 }, |
| 158 | { 1, -1, -6, 105, 40, -14, 4, -1 }, { 1, -1, -7, 104, 42, -14, 4, -1 }, |
| 159 | { 1, -1, -7, 103, 44, -15, 4, -1 }, { 1, 0, -8, 101, 46, -15, 4, -1 }, |
| 160 | { 1, 0, -9, 100, 48, -15, 4, -1 }, { 1, 0, -10, 99, 50, -15, 4, -1 }, |
| 161 | { 1, 1, -11, 97, 53, -16, 4, -1 }, { 0, 1, -11, 96, 55, -16, 4, -1 }, |
| 162 | { 0, 1, -12, 95, 57, -16, 4, -1 }, { 0, 2, -13, 93, 59, -16, 4, -1 }, |
| 163 | { 0, 2, -13, 91, 61, -16, 4, -1 }, { 0, 2, -14, 90, 63, -16, 4, -1 }, |
| 164 | { 0, 2, -14, 88, 65, -16, 4, -1 }, { 0, 2, -15, 86, 67, -16, 4, 0 }, |
| 165 | { 0, 3, -15, 84, 69, -17, 4, 0 }, { 0, 3, -16, 83, 71, -17, 4, 0 }, |
| 166 | { 0, 3, -16, 81, 73, -16, 3, 0 }, { 0, 3, -16, 79, 75, -16, 3, 0 }, |
| 167 | { 0, 3, -16, 77, 77, -16, 3, 0 }, { 0, 3, -16, 75, 79, -16, 3, 0 }, |
| 168 | { 0, 3, -16, 73, 81, -16, 3, 0 }, { 0, 4, -17, 71, 83, -16, 3, 0 }, |
| 169 | { 0, 4, -17, 69, 84, -15, 3, 0 }, { 0, 4, -16, 67, 86, -15, 2, 0 }, |
| 170 | { -1, 4, -16, 65, 88, -14, 2, 0 }, { -1, 4, -16, 63, 90, -14, 2, 0 }, |
| 171 | { -1, 4, -16, 61, 91, -13, 2, 0 }, { -1, 4, -16, 59, 93, -13, 2, 0 }, |
| 172 | { -1, 4, -16, 57, 95, -12, 1, 0 }, { -1, 4, -16, 55, 96, -11, 1, 0 }, |
| 173 | { -1, 4, -16, 53, 97, -11, 1, 1 }, { -1, 4, -15, 50, 99, -10, 0, 1 }, |
| 174 | { -1, 4, -15, 48, 100, -9, 0, 1 }, { -1, 4, -15, 46, 101, -8, 0, 1 }, |
| 175 | { -1, 4, -15, 44, 103, -7, -1, 1 }, { -1, 4, -14, 42, 104, -7, -1, 1 }, |
| 176 | { -1, 4, -14, 40, 105, -6, -1, 1 }, { -1, 4, -13, 38, 106, -5, -2, 1 }, |
| 177 | { -1, 4, -13, 36, 107, -4, -2, 1 }, { -1, 4, -13, 34, 108, -2, -3, 1 }, |
| 178 | { -1, 4, -12, 32, 108, -1, -3, 1 }, { -1, 4, -12, 30, 109, 0, -4, 2 }, |
| 179 | { -1, 3, -11, 28, 110, 1, -4, 2 }, { -1, 3, -11, 26, 110, 3, -4, 2 }, |
| 180 | { -1, 3, -10, 24, 111, 4, -5, 2 }, { -1, 3, -10, 22, 111, 6, -5, 2 }, |
| 181 | { -1, 3, -10, 21, 112, 7, -6, 2 }, { -1, 3, -9, 19, 112, 8, -6, 2 }, |
| 182 | { -1, 3, -9, 17, 112, 10, -7, 3 }, { -1, 3, -8, 15, 112, 12, -7, 2 }, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 183 | }; |
| 184 | |
| 185 | // Filters for interpolation (full-band) - no filtering for integer pixels |
Fergus Simpson | 090bb60 | 2017-04-07 12:37:53 -0700 | [diff] [blame] | 186 | static const interp_kernel filteredinterp_filters1000[(1 << SUBPEL_BITS_RS)] = { |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 187 | { 0, 0, 0, 128, 0, 0, 0, 0 }, { 0, 0, -1, 128, 2, -1, 0, 0 }, |
| 188 | { 0, 1, -3, 127, 4, -2, 1, 0 }, { 0, 1, -4, 127, 6, -3, 1, 0 }, |
| 189 | { 0, 2, -6, 126, 8, -3, 1, 0 }, { 0, 2, -7, 125, 11, -4, 1, 0 }, |
| 190 | { -1, 2, -8, 125, 13, -5, 2, 0 }, { -1, 3, -9, 124, 15, -6, 2, 0 }, |
| 191 | { -1, 3, -10, 123, 18, -6, 2, -1 }, { -1, 3, -11, 122, 20, -7, 3, -1 }, |
| 192 | { -1, 4, -12, 121, 22, -8, 3, -1 }, { -1, 4, -13, 120, 25, -9, 3, -1 }, |
| 193 | { -1, 4, -14, 118, 28, -9, 3, -1 }, { -1, 4, -15, 117, 30, -10, 4, -1 }, |
| 194 | { -1, 5, -16, 116, 32, -11, 4, -1 }, { -1, 5, -16, 114, 35, -12, 4, -1 }, |
| 195 | { -1, 5, -17, 112, 38, -12, 4, -1 }, { -1, 5, -18, 111, 40, -13, 5, -1 }, |
| 196 | { -1, 5, -18, 109, 43, -14, 5, -1 }, { -1, 6, -19, 107, 45, -14, 5, -1 }, |
| 197 | { -1, 6, -19, 105, 48, -15, 5, -1 }, { -1, 6, -19, 103, 51, -16, 5, -1 }, |
| 198 | { -1, 6, -20, 101, 53, -16, 6, -1 }, { -1, 6, -20, 99, 56, -17, 6, -1 }, |
| 199 | { -1, 6, -20, 97, 58, -17, 6, -1 }, { -1, 6, -20, 95, 61, -18, 6, -1 }, |
| 200 | { -2, 7, -20, 93, 64, -18, 6, -2 }, { -2, 7, -20, 91, 66, -19, 6, -1 }, |
| 201 | { -2, 7, -20, 88, 69, -19, 6, -1 }, { -2, 7, -20, 86, 71, -19, 6, -1 }, |
| 202 | { -2, 7, -20, 84, 74, -20, 7, -2 }, { -2, 7, -20, 81, 76, -20, 7, -1 }, |
| 203 | { -2, 7, -20, 79, 79, -20, 7, -2 }, { -1, 7, -20, 76, 81, -20, 7, -2 }, |
| 204 | { -2, 7, -20, 74, 84, -20, 7, -2 }, { -1, 6, -19, 71, 86, -20, 7, -2 }, |
| 205 | { -1, 6, -19, 69, 88, -20, 7, -2 }, { -1, 6, -19, 66, 91, -20, 7, -2 }, |
| 206 | { -2, 6, -18, 64, 93, -20, 7, -2 }, { -1, 6, -18, 61, 95, -20, 6, -1 }, |
| 207 | { -1, 6, -17, 58, 97, -20, 6, -1 }, { -1, 6, -17, 56, 99, -20, 6, -1 }, |
| 208 | { -1, 6, -16, 53, 101, -20, 6, -1 }, { -1, 5, -16, 51, 103, -19, 6, -1 }, |
| 209 | { -1, 5, -15, 48, 105, -19, 6, -1 }, { -1, 5, -14, 45, 107, -19, 6, -1 }, |
| 210 | { -1, 5, -14, 43, 109, -18, 5, -1 }, { -1, 5, -13, 40, 111, -18, 5, -1 }, |
| 211 | { -1, 4, -12, 38, 112, -17, 5, -1 }, { -1, 4, -12, 35, 114, -16, 5, -1 }, |
| 212 | { -1, 4, -11, 32, 116, -16, 5, -1 }, { -1, 4, -10, 30, 117, -15, 4, -1 }, |
| 213 | { -1, 3, -9, 28, 118, -14, 4, -1 }, { -1, 3, -9, 25, 120, -13, 4, -1 }, |
| 214 | { -1, 3, -8, 22, 121, -12, 4, -1 }, { -1, 3, -7, 20, 122, -11, 3, -1 }, |
| 215 | { -1, 2, -6, 18, 123, -10, 3, -1 }, { 0, 2, -6, 15, 124, -9, 3, -1 }, |
| 216 | { 0, 2, -5, 13, 125, -8, 2, -1 }, { 0, 1, -4, 11, 125, -7, 2, 0 }, |
| 217 | { 0, 1, -3, 8, 126, -6, 2, 0 }, { 0, 1, -3, 6, 127, -4, 1, 0 }, |
| 218 | { 0, 1, -2, 4, 127, -3, 1, 0 }, { 0, 0, -1, 2, 128, -1, 0, 0 }, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 219 | }; |
| 220 | |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 221 | #if CONFIG_FRAME_SUPERRES && CONFIG_LOOP_RESTORATION |
| 222 | #define INTERP_SIMPLE_TAPS 4 |
| 223 | static const int16_t filter_simple[(1 |
| 224 | << SUBPEL_BITS_RS)][INTERP_SIMPLE_TAPS] = { |
| 225 | #if INTERP_SIMPLE_TAPS == 2 |
| 226 | { 128, 0 }, { 126, 2 }, { 124, 4 }, { 122, 6 }, { 120, 8 }, { 118, 10 }, |
| 227 | { 116, 12 }, { 114, 14 }, { 112, 16 }, { 110, 18 }, { 108, 20 }, { 106, 22 }, |
| 228 | { 104, 24 }, { 102, 26 }, { 100, 28 }, { 98, 30 }, { 96, 32 }, { 94, 34 }, |
| 229 | { 92, 36 }, { 90, 38 }, { 88, 40 }, { 86, 42 }, { 84, 44 }, { 82, 46 }, |
| 230 | { 80, 48 }, { 78, 50 }, { 76, 52 }, { 74, 54 }, { 72, 56 }, { 70, 58 }, |
| 231 | { 68, 60 }, { 66, 62 }, { 64, 64 }, { 62, 66 }, { 60, 68 }, { 58, 70 }, |
| 232 | { 56, 72 }, { 54, 74 }, { 52, 76 }, { 50, 78 }, { 48, 80 }, { 46, 82 }, |
| 233 | { 44, 84 }, { 42, 86 }, { 40, 88 }, { 38, 90 }, { 36, 92 }, { 34, 94 }, |
| 234 | { 32, 96 }, { 30, 98 }, { 28, 100 }, { 26, 102 }, { 24, 104 }, { 22, 106 }, |
| 235 | { 20, 108 }, { 18, 110 }, { 16, 112 }, { 14, 114 }, { 12, 116 }, { 10, 118 }, |
| 236 | { 8, 120 }, { 6, 122 }, { 4, 124 }, { 2, 126 }, |
| 237 | #elif INTERP_SIMPLE_TAPS == 4 |
| 238 | { 0, 128, 0, 0 }, { -1, 128, 2, -1 }, { -2, 127, 4, -1 }, |
Debargha Mukherjee | 6ec3d6e | 2017-08-21 18:59:59 -0700 | [diff] [blame] | 239 | { -3, 126, 7, -2 }, { -4, 125, 9, -2 }, { -5, 125, 11, -3 }, |
| 240 | { -6, 124, 13, -3 }, { -7, 123, 16, -4 }, { -7, 122, 18, -5 }, |
| 241 | { -8, 121, 20, -5 }, { -9, 120, 23, -6 }, { -9, 118, 25, -6 }, |
| 242 | { -10, 117, 28, -7 }, { -11, 116, 30, -7 }, { -11, 114, 33, -8 }, |
| 243 | { -12, 113, 35, -8 }, { -12, 111, 38, -9 }, { -13, 109, 41, -9 }, |
| 244 | { -13, 108, 43, -10 }, { -13, 106, 45, -10 }, { -13, 104, 48, -11 }, |
| 245 | { -14, 102, 51, -11 }, { -14, 100, 53, -11 }, { -14, 98, 56, -12 }, |
| 246 | { -14, 96, 58, -12 }, { -14, 94, 61, -13 }, { -15, 92, 64, -13 }, |
| 247 | { -15, 90, 66, -13 }, { -15, 87, 69, -13 }, { -14, 85, 71, -14 }, |
| 248 | { -14, 83, 73, -14 }, { -14, 80, 76, -14 }, { -14, 78, 78, -14 }, |
| 249 | { -14, 76, 80, -14 }, { -14, 73, 83, -14 }, { -14, 71, 85, -14 }, |
| 250 | { -13, 69, 87, -15 }, { -13, 66, 90, -15 }, { -13, 64, 92, -15 }, |
| 251 | { -13, 61, 94, -14 }, { -12, 58, 96, -14 }, { -12, 56, 98, -14 }, |
| 252 | { -11, 53, 100, -14 }, { -11, 51, 102, -14 }, { -11, 48, 104, -13 }, |
| 253 | { -10, 45, 106, -13 }, { -10, 43, 108, -13 }, { -9, 41, 109, -13 }, |
| 254 | { -9, 38, 111, -12 }, { -8, 35, 113, -12 }, { -8, 33, 114, -11 }, |
| 255 | { -7, 30, 116, -11 }, { -7, 28, 117, -10 }, { -6, 25, 118, -9 }, |
| 256 | { -6, 23, 120, -9 }, { -5, 20, 121, -8 }, { -5, 18, 122, -7 }, |
| 257 | { -4, 16, 123, -7 }, { -3, 13, 124, -6 }, { -3, 11, 125, -5 }, |
| 258 | { -2, 9, 125, -4 }, { -2, 7, 126, -3 }, { -1, 4, 127, -2 }, |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 259 | { -1, 2, 128, -1 }, |
| 260 | #elif INTERP_SIMPLE_TAPS == 6 |
| 261 | { 0, 0, 128, 0, 0, 0 }, { 0, -1, 128, 2, -1, 0 }, |
| 262 | { 1, -3, 127, 4, -2, 1 }, { 1, -4, 127, 6, -3, 1 }, |
| 263 | { 2, -6, 126, 8, -3, 1 }, { 2, -7, 125, 11, -4, 1 }, |
| 264 | { 2, -9, 125, 13, -5, 2 }, { 3, -10, 124, 15, -6, 2 }, |
| 265 | { 3, -11, 123, 18, -7, 2 }, { 3, -12, 122, 20, -8, 3 }, |
| 266 | { 4, -13, 121, 22, -9, 3 }, { 4, -14, 119, 25, -9, 3 }, |
| 267 | { 4, -15, 118, 27, -10, 4 }, { 4, -16, 117, 30, -11, 4 }, |
| 268 | { 5, -17, 116, 32, -12, 4 }, { 5, -17, 114, 35, -13, 4 }, |
| 269 | { 5, -18, 112, 37, -13, 5 }, { 5, -19, 111, 40, -14, 5 }, |
| 270 | { 6, -19, 109, 42, -15, 5 }, { 6, -20, 107, 45, -15, 5 }, |
| 271 | { 6, -20, 105, 48, -16, 5 }, { 6, -21, 103, 51, -17, 6 }, |
| 272 | { 6, -21, 101, 53, -17, 6 }, { 6, -21, 99, 56, -18, 6 }, |
| 273 | { 7, -22, 97, 58, -18, 6 }, { 7, -22, 95, 61, -19, 6 }, |
| 274 | { 7, -22, 93, 63, -19, 6 }, { 7, -22, 91, 66, -20, 6 }, |
| 275 | { 7, -22, 88, 69, -20, 6 }, { 7, -22, 86, 71, -21, 7 }, |
| 276 | { 7, -22, 83, 74, -21, 7 }, { 7, -22, 81, 76, -21, 7 }, |
| 277 | { 7, -22, 79, 79, -22, 7 }, { 7, -21, 76, 81, -22, 7 }, |
| 278 | { 7, -21, 74, 83, -22, 7 }, { 7, -21, 71, 86, -22, 7 }, |
| 279 | { 6, -20, 69, 88, -22, 7 }, { 6, -20, 66, 91, -22, 7 }, |
| 280 | { 6, -19, 63, 93, -22, 7 }, { 6, -19, 61, 95, -22, 7 }, |
| 281 | { 6, -18, 58, 97, -22, 7 }, { 6, -18, 56, 99, -21, 6 }, |
| 282 | { 6, -17, 53, 101, -21, 6 }, { 6, -17, 51, 103, -21, 6 }, |
| 283 | { 5, -16, 48, 105, -20, 6 }, { 5, -15, 45, 107, -20, 6 }, |
| 284 | { 5, -15, 42, 109, -19, 6 }, { 5, -14, 40, 111, -19, 5 }, |
| 285 | { 5, -13, 37, 112, -18, 5 }, { 4, -13, 35, 114, -17, 5 }, |
| 286 | { 4, -12, 32, 116, -17, 5 }, { 4, -11, 30, 117, -16, 4 }, |
| 287 | { 4, -10, 27, 118, -15, 4 }, { 3, -9, 25, 119, -14, 4 }, |
| 288 | { 3, -9, 22, 121, -13, 4 }, { 3, -8, 20, 122, -12, 3 }, |
| 289 | { 2, -7, 18, 123, -11, 3 }, { 2, -6, 15, 124, -10, 3 }, |
| 290 | { 2, -5, 13, 125, -9, 2 }, { 1, -4, 11, 125, -7, 2 }, |
| 291 | { 1, -3, 8, 126, -6, 2 }, { 1, -3, 6, 127, -4, 1 }, |
| 292 | { 1, -2, 4, 127, -3, 1 }, { 0, -1, 2, 128, -1, 0 }, |
| 293 | #else |
| 294 | #error "Invalid value of INTERP_SIMPLE_TAPS" |
| 295 | #endif // INTERP_SIMPLE_TAPS == 2 |
| 296 | }; |
| 297 | #endif // CONFIG_FRAME_SUPERRES && CONFIG_LOOP_RESTORATION |
| 298 | |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 299 | // Filters for factor of 2 downsampling. |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 300 | static const int16_t av1_down2_symeven_half_filter[] = { 56, 12, -3, -1 }; |
| 301 | static const int16_t av1_down2_symodd_half_filter[] = { 64, 35, 0, -3 }; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 302 | |
| 303 | static const interp_kernel *choose_interp_filter(int inlength, int outlength) { |
| 304 | int outlength16 = outlength * 16; |
| 305 | if (outlength16 >= inlength * 16) |
| 306 | return filteredinterp_filters1000; |
| 307 | else if (outlength16 >= inlength * 13) |
| 308 | return filteredinterp_filters875; |
| 309 | else if (outlength16 >= inlength * 11) |
| 310 | return filteredinterp_filters750; |
| 311 | else if (outlength16 >= inlength * 9) |
| 312 | return filteredinterp_filters625; |
| 313 | else |
| 314 | return filteredinterp_filters500; |
| 315 | } |
| 316 | |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 317 | static void interpolate_core(const uint8_t *const input, int inlength, |
| 318 | uint8_t *output, int outlength, |
| 319 | const int16_t *interp_filters, int interp_taps) { |
| 320 | const int32_t delta = |
| 321 | (((uint32_t)inlength << INTERP_PRECISION_BITS) + outlength / 2) / |
| 322 | outlength; |
| 323 | const int32_t offset = |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 324 | inlength > outlength |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 325 | ? (((int32_t)(inlength - outlength) << (INTERP_PRECISION_BITS - 1)) + |
| 326 | outlength / 2) / |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 327 | outlength |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 328 | : -(((int32_t)(outlength - inlength) << (INTERP_PRECISION_BITS - 1)) + |
| 329 | outlength / 2) / |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 330 | outlength; |
| 331 | uint8_t *optr = output; |
| 332 | int x, x1, x2, sum, k, int_pel, sub_pel; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 333 | int32_t y; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 334 | |
| 335 | x = 0; |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 336 | y = offset + SUBPEL_INTERP_EXTRA_OFF; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 337 | while ((y >> INTERP_PRECISION_BITS) < (interp_taps / 2 - 1)) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 338 | x++; |
| 339 | y += delta; |
| 340 | } |
| 341 | x1 = x; |
| 342 | x = outlength - 1; |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 343 | y = delta * x + offset + SUBPEL_INTERP_EXTRA_OFF; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 344 | while ((y >> INTERP_PRECISION_BITS) + (int32_t)(interp_taps / 2) >= |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 345 | inlength) { |
| 346 | x--; |
| 347 | y -= delta; |
| 348 | } |
| 349 | x2 = x; |
| 350 | if (x1 > x2) { |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 351 | for (x = 0, y = offset + SUBPEL_INTERP_EXTRA_OFF; x < outlength; |
| 352 | ++x, y += delta) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 353 | int_pel = y >> INTERP_PRECISION_BITS; |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 354 | sub_pel = (y >> SUBPEL_INTERP_EXTRA_BITS) & SUBPEL_MASK_RS; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 355 | const int16_t *filter = &interp_filters[sub_pel * interp_taps]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 356 | sum = 0; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 357 | for (k = 0; k < interp_taps; ++k) { |
| 358 | const int pk = int_pel - interp_taps / 2 + 1 + k; |
Sebastien Alaiwan | 0b95a6e | 2017-05-04 13:03:35 +0200 | [diff] [blame] | 359 | sum += filter[k] * input[AOMMAX(AOMMIN(pk, inlength - 1), 0)]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 360 | } |
| 361 | *optr++ = clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS)); |
| 362 | } |
| 363 | } else { |
| 364 | // Initial part. |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 365 | for (x = 0, y = offset + SUBPEL_INTERP_EXTRA_OFF; x < x1; ++x, y += delta) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 366 | int_pel = y >> INTERP_PRECISION_BITS; |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 367 | sub_pel = (y >> SUBPEL_INTERP_EXTRA_BITS) & SUBPEL_MASK_RS; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 368 | const int16_t *filter = &interp_filters[sub_pel * interp_taps]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 369 | sum = 0; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 370 | for (k = 0; k < interp_taps; ++k) |
| 371 | sum += filter[k] * input[AOMMAX(int_pel - interp_taps / 2 + 1 + k, 0)]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 372 | *optr++ = clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS)); |
| 373 | } |
| 374 | // Middle part. |
| 375 | for (; x <= x2; ++x, y += delta) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 376 | int_pel = y >> INTERP_PRECISION_BITS; |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 377 | sub_pel = (y >> SUBPEL_INTERP_EXTRA_BITS) & SUBPEL_MASK_RS; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 378 | const int16_t *filter = &interp_filters[sub_pel * interp_taps]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 379 | sum = 0; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 380 | for (k = 0; k < interp_taps; ++k) |
| 381 | sum += filter[k] * input[int_pel - interp_taps / 2 + 1 + k]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 382 | *optr++ = clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS)); |
| 383 | } |
| 384 | // End part. |
| 385 | for (; x < outlength; ++x, y += delta) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 386 | int_pel = y >> INTERP_PRECISION_BITS; |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 387 | sub_pel = (y >> SUBPEL_INTERP_EXTRA_BITS) & SUBPEL_MASK_RS; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 388 | const int16_t *filter = &interp_filters[sub_pel * interp_taps]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 389 | sum = 0; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 390 | for (k = 0; k < interp_taps; ++k) |
Sebastien Alaiwan | 0b95a6e | 2017-05-04 13:03:35 +0200 | [diff] [blame] | 391 | sum += filter[k] * |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 392 | input[AOMMIN(int_pel - interp_taps / 2 + 1 + k, inlength - 1)]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 393 | *optr++ = clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS)); |
| 394 | } |
| 395 | } |
| 396 | } |
| 397 | |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 398 | static void interpolate(const uint8_t *const input, int inlength, |
| 399 | uint8_t *output, int outlength) { |
| 400 | const interp_kernel *interp_filters = |
| 401 | choose_interp_filter(inlength, outlength); |
| 402 | |
| 403 | interpolate_core(input, inlength, output, outlength, &interp_filters[0][0], |
| 404 | INTERP_TAPS); |
| 405 | } |
| 406 | |
| 407 | #if CONFIG_FRAME_SUPERRES && CONFIG_LOOP_RESTORATION |
| 408 | static void interpolate_simple(const uint8_t *const input, int inlength, |
| 409 | uint8_t *output, int outlength) { |
| 410 | interpolate_core(input, inlength, output, outlength, &filter_simple[0][0], |
| 411 | INTERP_SIMPLE_TAPS); |
| 412 | } |
| 413 | #endif // CONFIG_FRAME_SUPERRES && CONFIG_LOOP_RESTORATION |
| 414 | |
Sebastien Alaiwan | 92400ab | 2017-03-14 10:39:29 +0100 | [diff] [blame] | 415 | #ifndef __clang_analyzer__ |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 416 | static void down2_symeven(const uint8_t *const input, int length, |
| 417 | uint8_t *output) { |
| 418 | // Actual filter len = 2 * filter_len_half. |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 419 | const int16_t *filter = av1_down2_symeven_half_filter; |
| 420 | const int filter_len_half = sizeof(av1_down2_symeven_half_filter) / 2; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 421 | int i, j; |
| 422 | uint8_t *optr = output; |
| 423 | int l1 = filter_len_half; |
| 424 | int l2 = (length - filter_len_half); |
| 425 | l1 += (l1 & 1); |
| 426 | l2 += (l2 & 1); |
| 427 | if (l1 > l2) { |
| 428 | // Short input length. |
| 429 | for (i = 0; i < length; i += 2) { |
| 430 | int sum = (1 << (FILTER_BITS - 1)); |
| 431 | for (j = 0; j < filter_len_half; ++j) { |
Sebastien Alaiwan | 0b95a6e | 2017-05-04 13:03:35 +0200 | [diff] [blame] | 432 | sum += |
| 433 | (input[AOMMAX(i - j, 0)] + input[AOMMIN(i + 1 + j, length - 1)]) * |
| 434 | filter[j]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 435 | } |
| 436 | sum >>= FILTER_BITS; |
| 437 | *optr++ = clip_pixel(sum); |
| 438 | } |
| 439 | } else { |
| 440 | // Initial part. |
| 441 | for (i = 0; i < l1; i += 2) { |
| 442 | int sum = (1 << (FILTER_BITS - 1)); |
| 443 | for (j = 0; j < filter_len_half; ++j) { |
Sebastien Alaiwan | 0b95a6e | 2017-05-04 13:03:35 +0200 | [diff] [blame] | 444 | sum += (input[AOMMAX(i - j, 0)] + input[i + 1 + j]) * filter[j]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 445 | } |
| 446 | sum >>= FILTER_BITS; |
| 447 | *optr++ = clip_pixel(sum); |
| 448 | } |
| 449 | // Middle part. |
| 450 | for (; i < l2; i += 2) { |
| 451 | int sum = (1 << (FILTER_BITS - 1)); |
| 452 | for (j = 0; j < filter_len_half; ++j) { |
| 453 | sum += (input[i - j] + input[i + 1 + j]) * filter[j]; |
| 454 | } |
| 455 | sum >>= FILTER_BITS; |
| 456 | *optr++ = clip_pixel(sum); |
| 457 | } |
| 458 | // End part. |
| 459 | for (; i < length; i += 2) { |
| 460 | int sum = (1 << (FILTER_BITS - 1)); |
| 461 | for (j = 0; j < filter_len_half; ++j) { |
Sebastien Alaiwan | 0b95a6e | 2017-05-04 13:03:35 +0200 | [diff] [blame] | 462 | sum += |
| 463 | (input[i - j] + input[AOMMIN(i + 1 + j, length - 1)]) * filter[j]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 464 | } |
| 465 | sum >>= FILTER_BITS; |
| 466 | *optr++ = clip_pixel(sum); |
| 467 | } |
| 468 | } |
| 469 | } |
Sebastien Alaiwan | 92400ab | 2017-03-14 10:39:29 +0100 | [diff] [blame] | 470 | #endif |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 471 | |
| 472 | static void down2_symodd(const uint8_t *const input, int length, |
| 473 | uint8_t *output) { |
| 474 | // Actual filter len = 2 * filter_len_half - 1. |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 475 | const int16_t *filter = av1_down2_symodd_half_filter; |
| 476 | const int filter_len_half = sizeof(av1_down2_symodd_half_filter) / 2; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 477 | int i, j; |
| 478 | uint8_t *optr = output; |
| 479 | int l1 = filter_len_half - 1; |
| 480 | int l2 = (length - filter_len_half + 1); |
| 481 | l1 += (l1 & 1); |
| 482 | l2 += (l2 & 1); |
| 483 | if (l1 > l2) { |
| 484 | // Short input length. |
| 485 | for (i = 0; i < length; i += 2) { |
| 486 | int sum = (1 << (FILTER_BITS - 1)) + input[i] * filter[0]; |
| 487 | for (j = 1; j < filter_len_half; ++j) { |
| 488 | sum += (input[(i - j < 0 ? 0 : i - j)] + |
| 489 | input[(i + j >= length ? length - 1 : i + j)]) * |
| 490 | filter[j]; |
| 491 | } |
| 492 | sum >>= FILTER_BITS; |
| 493 | *optr++ = clip_pixel(sum); |
| 494 | } |
| 495 | } else { |
| 496 | // Initial part. |
| 497 | for (i = 0; i < l1; i += 2) { |
| 498 | int sum = (1 << (FILTER_BITS - 1)) + input[i] * filter[0]; |
| 499 | for (j = 1; j < filter_len_half; ++j) { |
| 500 | sum += (input[(i - j < 0 ? 0 : i - j)] + input[i + j]) * filter[j]; |
| 501 | } |
| 502 | sum >>= FILTER_BITS; |
| 503 | *optr++ = clip_pixel(sum); |
| 504 | } |
| 505 | // Middle part. |
| 506 | for (; i < l2; i += 2) { |
| 507 | int sum = (1 << (FILTER_BITS - 1)) + input[i] * filter[0]; |
| 508 | for (j = 1; j < filter_len_half; ++j) { |
| 509 | sum += (input[i - j] + input[i + j]) * filter[j]; |
| 510 | } |
| 511 | sum >>= FILTER_BITS; |
| 512 | *optr++ = clip_pixel(sum); |
| 513 | } |
| 514 | // End part. |
| 515 | for (; i < length; i += 2) { |
| 516 | int sum = (1 << (FILTER_BITS - 1)) + input[i] * filter[0]; |
| 517 | for (j = 1; j < filter_len_half; ++j) { |
| 518 | sum += (input[i - j] + input[(i + j >= length ? length - 1 : i + j)]) * |
| 519 | filter[j]; |
| 520 | } |
| 521 | sum >>= FILTER_BITS; |
| 522 | *optr++ = clip_pixel(sum); |
| 523 | } |
| 524 | } |
| 525 | } |
| 526 | |
| 527 | static int get_down2_length(int length, int steps) { |
| 528 | int s; |
| 529 | for (s = 0; s < steps; ++s) length = (length + 1) >> 1; |
| 530 | return length; |
| 531 | } |
| 532 | |
| 533 | static int get_down2_steps(int in_length, int out_length) { |
| 534 | int steps = 0; |
| 535 | int proj_in_length; |
| 536 | while ((proj_in_length = get_down2_length(in_length, 1)) >= out_length) { |
| 537 | ++steps; |
| 538 | in_length = proj_in_length; |
| 539 | } |
| 540 | return steps; |
| 541 | } |
| 542 | |
| 543 | static void resize_multistep(const uint8_t *const input, int length, |
| 544 | uint8_t *output, int olength, uint8_t *otmp) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 545 | if (length == olength) { |
| 546 | memcpy(output, input, sizeof(output[0]) * length); |
| 547 | return; |
| 548 | } |
Sebastien Alaiwan | 0b95a6e | 2017-05-04 13:03:35 +0200 | [diff] [blame] | 549 | const int steps = get_down2_steps(length, olength); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 550 | |
| 551 | if (steps > 0) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 552 | uint8_t *out = NULL; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 553 | int filteredlength = length; |
| 554 | |
| 555 | assert(otmp != NULL); |
Sebastien Alaiwan | e4ba6aa | 2017-05-04 14:18:30 +0200 | [diff] [blame] | 556 | uint8_t *otmp2 = otmp + get_down2_length(length, 1); |
| 557 | for (int s = 0; s < steps; ++s) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 558 | const int proj_filteredlength = get_down2_length(filteredlength, 1); |
| 559 | const uint8_t *const in = (s == 0 ? input : out); |
| 560 | if (s == steps - 1 && proj_filteredlength == olength) |
| 561 | out = output; |
| 562 | else |
| 563 | out = (s & 1 ? otmp2 : otmp); |
| 564 | if (filteredlength & 1) |
| 565 | down2_symodd(in, filteredlength, out); |
| 566 | else |
| 567 | down2_symeven(in, filteredlength, out); |
| 568 | filteredlength = proj_filteredlength; |
| 569 | } |
| 570 | if (filteredlength != olength) { |
| 571 | interpolate(out, filteredlength, output, olength); |
| 572 | } |
| 573 | } else { |
| 574 | interpolate(input, length, output, olength); |
| 575 | } |
| 576 | } |
| 577 | |
| 578 | static void fill_col_to_arr(uint8_t *img, int stride, int len, uint8_t *arr) { |
| 579 | int i; |
| 580 | uint8_t *iptr = img; |
| 581 | uint8_t *aptr = arr; |
| 582 | for (i = 0; i < len; ++i, iptr += stride) { |
| 583 | *aptr++ = *iptr; |
| 584 | } |
| 585 | } |
| 586 | |
| 587 | static void fill_arr_to_col(uint8_t *img, int stride, int len, uint8_t *arr) { |
| 588 | int i; |
| 589 | uint8_t *iptr = img; |
| 590 | uint8_t *aptr = arr; |
| 591 | for (i = 0; i < len; ++i, iptr += stride) { |
| 592 | *iptr = *aptr++; |
| 593 | } |
| 594 | } |
| 595 | |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 596 | static void resize_plane(const uint8_t *const input, int height, int width, |
| 597 | int in_stride, uint8_t *output, int height2, |
| 598 | int width2, int out_stride) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 599 | int i; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 600 | uint8_t *intbuf = (uint8_t *)aom_malloc(sizeof(uint8_t) * width2 * height); |
| 601 | uint8_t *tmpbuf = |
| 602 | (uint8_t *)aom_malloc(sizeof(uint8_t) * AOMMAX(width, height)); |
| 603 | uint8_t *arrbuf = (uint8_t *)aom_malloc(sizeof(uint8_t) * height); |
| 604 | uint8_t *arrbuf2 = (uint8_t *)aom_malloc(sizeof(uint8_t) * height2); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 605 | if (intbuf == NULL || tmpbuf == NULL || arrbuf == NULL || arrbuf2 == NULL) |
| 606 | goto Error; |
| 607 | assert(width > 0); |
| 608 | assert(height > 0); |
| 609 | assert(width2 > 0); |
| 610 | assert(height2 > 0); |
| 611 | for (i = 0; i < height; ++i) |
| 612 | resize_multistep(input + in_stride * i, width, intbuf + width2 * i, width2, |
| 613 | tmpbuf); |
| 614 | for (i = 0; i < width2; ++i) { |
| 615 | fill_col_to_arr(intbuf + i, width2, height, arrbuf); |
| 616 | resize_multistep(arrbuf, height, arrbuf2, height2, tmpbuf); |
| 617 | fill_arr_to_col(output + i, out_stride, height2, arrbuf2); |
| 618 | } |
| 619 | |
| 620 | Error: |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 621 | aom_free(intbuf); |
| 622 | aom_free(tmpbuf); |
| 623 | aom_free(arrbuf); |
| 624 | aom_free(arrbuf2); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 625 | } |
| 626 | |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 627 | #if CONFIG_FRAME_SUPERRES |
| 628 | static void upscale_normative(const uint8_t *const input, int length, |
| 629 | uint8_t *output, int olength) { |
| 630 | #if CONFIG_LOOP_RESTORATION |
| 631 | interpolate_simple(input, length, output, olength); |
| 632 | #else |
| 633 | interpolate(input, length, output, olength); |
| 634 | #endif // CONFIG_LOOP_RESTORATION |
| 635 | } |
| 636 | |
| 637 | static void upscale_normative_plane(const uint8_t *const input, int height, |
| 638 | int width, int in_stride, uint8_t *output, |
| 639 | int height2, int width2, int out_stride) { |
| 640 | int i; |
| 641 | uint8_t *intbuf = (uint8_t *)aom_malloc(sizeof(uint8_t) * width2 * height); |
| 642 | uint8_t *arrbuf = (uint8_t *)aom_malloc(sizeof(uint8_t) * height); |
| 643 | uint8_t *arrbuf2 = (uint8_t *)aom_malloc(sizeof(uint8_t) * height2); |
| 644 | if (intbuf == NULL || arrbuf == NULL || arrbuf2 == NULL) goto Error; |
| 645 | assert(width > 0); |
| 646 | assert(height > 0); |
| 647 | assert(width2 > 0); |
| 648 | assert(height2 > 0); |
| 649 | for (i = 0; i < height; ++i) |
| 650 | upscale_normative(input + in_stride * i, width, intbuf + width2 * i, |
| 651 | width2); |
| 652 | for (i = 0; i < width2; ++i) { |
| 653 | fill_col_to_arr(intbuf + i, width2, height, arrbuf); |
| 654 | upscale_normative(arrbuf, height, arrbuf2, height2); |
| 655 | fill_arr_to_col(output + i, out_stride, height2, arrbuf2); |
| 656 | } |
| 657 | |
| 658 | Error: |
| 659 | aom_free(intbuf); |
| 660 | aom_free(arrbuf); |
| 661 | aom_free(arrbuf2); |
| 662 | } |
| 663 | #endif // CONFIG_FRAME_SUPERRES |
| 664 | |
Sebastien Alaiwan | 71e8784 | 2017-04-12 16:03:28 +0200 | [diff] [blame] | 665 | #if CONFIG_HIGHBITDEPTH |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 666 | static void highbd_interpolate_core(const uint16_t *const input, int inlength, |
| 667 | uint16_t *output, int outlength, int bd, |
| 668 | const int16_t *interp_filters, |
| 669 | int interp_taps) { |
| 670 | const int32_t delta = |
| 671 | (((uint32_t)inlength << INTERP_PRECISION_BITS) + outlength / 2) / |
| 672 | outlength; |
| 673 | const int32_t offset = |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 674 | inlength > outlength |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 675 | ? (((int32_t)(inlength - outlength) << (INTERP_PRECISION_BITS - 1)) + |
| 676 | outlength / 2) / |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 677 | outlength |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 678 | : -(((int32_t)(outlength - inlength) << (INTERP_PRECISION_BITS - 1)) + |
| 679 | outlength / 2) / |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 680 | outlength; |
| 681 | uint16_t *optr = output; |
| 682 | int x, x1, x2, sum, k, int_pel, sub_pel; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 683 | int32_t y; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 684 | |
| 685 | x = 0; |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 686 | y = offset + SUBPEL_INTERP_EXTRA_OFF; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 687 | while ((y >> INTERP_PRECISION_BITS) < (interp_taps / 2 - 1)) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 688 | x++; |
| 689 | y += delta; |
| 690 | } |
| 691 | x1 = x; |
| 692 | x = outlength - 1; |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 693 | y = delta * x + offset + SUBPEL_INTERP_EXTRA_OFF; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 694 | while ((y >> INTERP_PRECISION_BITS) + (int32_t)(interp_taps / 2) >= |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 695 | inlength) { |
| 696 | x--; |
| 697 | y -= delta; |
| 698 | } |
| 699 | x2 = x; |
| 700 | if (x1 > x2) { |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 701 | for (x = 0, y = offset + SUBPEL_INTERP_EXTRA_OFF; x < outlength; |
| 702 | ++x, y += delta) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 703 | int_pel = y >> INTERP_PRECISION_BITS; |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 704 | sub_pel = (y >> SUBPEL_INTERP_EXTRA_BITS) & SUBPEL_MASK_RS; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 705 | const int16_t *filter = &interp_filters[sub_pel * interp_taps]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 706 | sum = 0; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 707 | for (k = 0; k < interp_taps; ++k) { |
| 708 | const int pk = int_pel - interp_taps / 2 + 1 + k; |
Sebastien Alaiwan | 0b95a6e | 2017-05-04 13:03:35 +0200 | [diff] [blame] | 709 | sum += filter[k] * input[AOMMAX(AOMMIN(pk, inlength - 1), 0)]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 710 | } |
| 711 | *optr++ = clip_pixel_highbd(ROUND_POWER_OF_TWO(sum, FILTER_BITS), bd); |
| 712 | } |
| 713 | } else { |
| 714 | // Initial part. |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 715 | for (x = 0, y = offset + SUBPEL_INTERP_EXTRA_OFF; x < x1; ++x, y += delta) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 716 | int_pel = y >> INTERP_PRECISION_BITS; |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 717 | sub_pel = (y >> SUBPEL_INTERP_EXTRA_BITS) & SUBPEL_MASK_RS; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 718 | const int16_t *filter = &interp_filters[sub_pel * interp_taps]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 719 | sum = 0; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 720 | for (k = 0; k < interp_taps; ++k) |
| 721 | sum += filter[k] * input[AOMMAX(int_pel - interp_taps / 2 + 1 + k, 0)]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 722 | *optr++ = clip_pixel_highbd(ROUND_POWER_OF_TWO(sum, FILTER_BITS), bd); |
| 723 | } |
| 724 | // Middle part. |
| 725 | for (; x <= x2; ++x, y += delta) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 726 | int_pel = y >> INTERP_PRECISION_BITS; |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 727 | sub_pel = (y >> SUBPEL_INTERP_EXTRA_BITS) & SUBPEL_MASK_RS; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 728 | const int16_t *filter = &interp_filters[sub_pel * interp_taps]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 729 | sum = 0; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 730 | for (k = 0; k < interp_taps; ++k) |
| 731 | sum += filter[k] * input[int_pel - interp_taps / 2 + 1 + k]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 732 | *optr++ = clip_pixel_highbd(ROUND_POWER_OF_TWO(sum, FILTER_BITS), bd); |
| 733 | } |
| 734 | // End part. |
| 735 | for (; x < outlength; ++x, y += delta) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 736 | int_pel = y >> INTERP_PRECISION_BITS; |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 737 | sub_pel = (y >> SUBPEL_INTERP_EXTRA_BITS) & SUBPEL_MASK_RS; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 738 | const int16_t *filter = &interp_filters[sub_pel * interp_taps]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 739 | sum = 0; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 740 | for (k = 0; k < interp_taps; ++k) |
Sebastien Alaiwan | 0b95a6e | 2017-05-04 13:03:35 +0200 | [diff] [blame] | 741 | sum += filter[k] * |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 742 | input[AOMMIN(int_pel - interp_taps / 2 + 1 + k, inlength - 1)]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 743 | *optr++ = clip_pixel_highbd(ROUND_POWER_OF_TWO(sum, FILTER_BITS), bd); |
| 744 | } |
| 745 | } |
| 746 | } |
Debargha Mukherjee | 65b80fd | 2017-07-03 22:33:04 -0700 | [diff] [blame] | 747 | |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 748 | static void highbd_interpolate(const uint16_t *const input, int inlength, |
| 749 | uint16_t *output, int outlength, int bd) { |
| 750 | const interp_kernel *interp_filters = |
| 751 | choose_interp_filter(inlength, outlength); |
| 752 | |
| 753 | highbd_interpolate_core(input, inlength, output, outlength, bd, |
| 754 | &interp_filters[0][0], INTERP_TAPS); |
| 755 | } |
| 756 | |
| 757 | #if CONFIG_FRAME_SUPERRES && CONFIG_LOOP_RESTORATION |
| 758 | static void highbd_interpolate_simple(const uint16_t *const input, int inlength, |
| 759 | uint16_t *output, int outlength, int bd) { |
| 760 | highbd_interpolate_core(input, inlength, output, outlength, bd, |
| 761 | &filter_simple[0][0], INTERP_SIMPLE_TAPS); |
| 762 | } |
| 763 | #endif // CONFIG_FRAME_SUPERRES && CONFIG_LOOP_RESTORATION |
| 764 | |
Sebastien Alaiwan | 92400ab | 2017-03-14 10:39:29 +0100 | [diff] [blame] | 765 | #ifndef __clang_analyzer__ |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 766 | static void highbd_down2_symeven(const uint16_t *const input, int length, |
| 767 | uint16_t *output, int bd) { |
| 768 | // Actual filter len = 2 * filter_len_half. |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 769 | static const int16_t *filter = av1_down2_symeven_half_filter; |
| 770 | const int filter_len_half = sizeof(av1_down2_symeven_half_filter) / 2; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 771 | int i, j; |
| 772 | uint16_t *optr = output; |
| 773 | int l1 = filter_len_half; |
| 774 | int l2 = (length - filter_len_half); |
| 775 | l1 += (l1 & 1); |
| 776 | l2 += (l2 & 1); |
| 777 | if (l1 > l2) { |
| 778 | // Short input length. |
| 779 | for (i = 0; i < length; i += 2) { |
| 780 | int sum = (1 << (FILTER_BITS - 1)); |
| 781 | for (j = 0; j < filter_len_half; ++j) { |
Sebastien Alaiwan | 0b95a6e | 2017-05-04 13:03:35 +0200 | [diff] [blame] | 782 | sum += |
| 783 | (input[AOMMAX(0, i - j)] + input[AOMMIN(i + 1 + j, length - 1)]) * |
| 784 | filter[j]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 785 | } |
| 786 | sum >>= FILTER_BITS; |
| 787 | *optr++ = clip_pixel_highbd(sum, bd); |
| 788 | } |
| 789 | } else { |
| 790 | // Initial part. |
| 791 | for (i = 0; i < l1; i += 2) { |
| 792 | int sum = (1 << (FILTER_BITS - 1)); |
| 793 | for (j = 0; j < filter_len_half; ++j) { |
Sebastien Alaiwan | 0b95a6e | 2017-05-04 13:03:35 +0200 | [diff] [blame] | 794 | sum += (input[AOMMAX(0, i - j)] + input[i + 1 + j]) * filter[j]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 795 | } |
| 796 | sum >>= FILTER_BITS; |
| 797 | *optr++ = clip_pixel_highbd(sum, bd); |
| 798 | } |
| 799 | // Middle part. |
| 800 | for (; i < l2; i += 2) { |
| 801 | int sum = (1 << (FILTER_BITS - 1)); |
| 802 | for (j = 0; j < filter_len_half; ++j) { |
| 803 | sum += (input[i - j] + input[i + 1 + j]) * filter[j]; |
| 804 | } |
| 805 | sum >>= FILTER_BITS; |
| 806 | *optr++ = clip_pixel_highbd(sum, bd); |
| 807 | } |
| 808 | // End part. |
| 809 | for (; i < length; i += 2) { |
| 810 | int sum = (1 << (FILTER_BITS - 1)); |
| 811 | for (j = 0; j < filter_len_half; ++j) { |
Sebastien Alaiwan | 0b95a6e | 2017-05-04 13:03:35 +0200 | [diff] [blame] | 812 | sum += |
| 813 | (input[i - j] + input[AOMMIN(i + 1 + j, length - 1)]) * filter[j]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 814 | } |
| 815 | sum >>= FILTER_BITS; |
| 816 | *optr++ = clip_pixel_highbd(sum, bd); |
| 817 | } |
| 818 | } |
| 819 | } |
| 820 | |
| 821 | static void highbd_down2_symodd(const uint16_t *const input, int length, |
| 822 | uint16_t *output, int bd) { |
| 823 | // Actual filter len = 2 * filter_len_half - 1. |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 824 | static const int16_t *filter = av1_down2_symodd_half_filter; |
| 825 | const int filter_len_half = sizeof(av1_down2_symodd_half_filter) / 2; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 826 | int i, j; |
| 827 | uint16_t *optr = output; |
| 828 | int l1 = filter_len_half - 1; |
| 829 | int l2 = (length - filter_len_half + 1); |
| 830 | l1 += (l1 & 1); |
| 831 | l2 += (l2 & 1); |
| 832 | if (l1 > l2) { |
| 833 | // Short input length. |
| 834 | for (i = 0; i < length; i += 2) { |
| 835 | int sum = (1 << (FILTER_BITS - 1)) + input[i] * filter[0]; |
| 836 | for (j = 1; j < filter_len_half; ++j) { |
Sebastien Alaiwan | 0b95a6e | 2017-05-04 13:03:35 +0200 | [diff] [blame] | 837 | sum += (input[AOMMAX(i - j, 0)] + input[AOMMIN(i + j, length - 1)]) * |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 838 | filter[j]; |
| 839 | } |
| 840 | sum >>= FILTER_BITS; |
| 841 | *optr++ = clip_pixel_highbd(sum, bd); |
| 842 | } |
| 843 | } else { |
| 844 | // Initial part. |
| 845 | for (i = 0; i < l1; i += 2) { |
| 846 | int sum = (1 << (FILTER_BITS - 1)) + input[i] * filter[0]; |
| 847 | for (j = 1; j < filter_len_half; ++j) { |
Sebastien Alaiwan | 0b95a6e | 2017-05-04 13:03:35 +0200 | [diff] [blame] | 848 | sum += (input[AOMMAX(i - j, 0)] + input[i + j]) * filter[j]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 849 | } |
| 850 | sum >>= FILTER_BITS; |
| 851 | *optr++ = clip_pixel_highbd(sum, bd); |
| 852 | } |
| 853 | // Middle part. |
| 854 | for (; i < l2; i += 2) { |
| 855 | int sum = (1 << (FILTER_BITS - 1)) + input[i] * filter[0]; |
| 856 | for (j = 1; j < filter_len_half; ++j) { |
| 857 | sum += (input[i - j] + input[i + j]) * filter[j]; |
| 858 | } |
| 859 | sum >>= FILTER_BITS; |
| 860 | *optr++ = clip_pixel_highbd(sum, bd); |
| 861 | } |
| 862 | // End part. |
| 863 | for (; i < length; i += 2) { |
| 864 | int sum = (1 << (FILTER_BITS - 1)) + input[i] * filter[0]; |
| 865 | for (j = 1; j < filter_len_half; ++j) { |
Sebastien Alaiwan | 0b95a6e | 2017-05-04 13:03:35 +0200 | [diff] [blame] | 866 | sum += (input[i - j] + input[AOMMIN(i + j, length - 1)]) * filter[j]; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 867 | } |
| 868 | sum >>= FILTER_BITS; |
| 869 | *optr++ = clip_pixel_highbd(sum, bd); |
| 870 | } |
| 871 | } |
| 872 | } |
Sebastien Alaiwan | 92400ab | 2017-03-14 10:39:29 +0100 | [diff] [blame] | 873 | #endif |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 874 | |
| 875 | static void highbd_resize_multistep(const uint16_t *const input, int length, |
| 876 | uint16_t *output, int olength, |
| 877 | uint16_t *otmp, int bd) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 878 | if (length == olength) { |
| 879 | memcpy(output, input, sizeof(output[0]) * length); |
| 880 | return; |
| 881 | } |
Sebastien Alaiwan | e4ba6aa | 2017-05-04 14:18:30 +0200 | [diff] [blame] | 882 | const int steps = get_down2_steps(length, olength); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 883 | |
| 884 | if (steps > 0) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 885 | uint16_t *out = NULL; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 886 | int filteredlength = length; |
| 887 | |
| 888 | assert(otmp != NULL); |
Sebastien Alaiwan | e4ba6aa | 2017-05-04 14:18:30 +0200 | [diff] [blame] | 889 | uint16_t *otmp2 = otmp + get_down2_length(length, 1); |
| 890 | for (int s = 0; s < steps; ++s) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 891 | const int proj_filteredlength = get_down2_length(filteredlength, 1); |
| 892 | const uint16_t *const in = (s == 0 ? input : out); |
| 893 | if (s == steps - 1 && proj_filteredlength == olength) |
| 894 | out = output; |
| 895 | else |
| 896 | out = (s & 1 ? otmp2 : otmp); |
| 897 | if (filteredlength & 1) |
| 898 | highbd_down2_symodd(in, filteredlength, out, bd); |
| 899 | else |
| 900 | highbd_down2_symeven(in, filteredlength, out, bd); |
| 901 | filteredlength = proj_filteredlength; |
| 902 | } |
| 903 | if (filteredlength != olength) { |
| 904 | highbd_interpolate(out, filteredlength, output, olength, bd); |
| 905 | } |
| 906 | } else { |
| 907 | highbd_interpolate(input, length, output, olength, bd); |
| 908 | } |
| 909 | } |
| 910 | |
| 911 | static void highbd_fill_col_to_arr(uint16_t *img, int stride, int len, |
| 912 | uint16_t *arr) { |
| 913 | int i; |
| 914 | uint16_t *iptr = img; |
| 915 | uint16_t *aptr = arr; |
| 916 | for (i = 0; i < len; ++i, iptr += stride) { |
| 917 | *aptr++ = *iptr; |
| 918 | } |
| 919 | } |
| 920 | |
| 921 | static void highbd_fill_arr_to_col(uint16_t *img, int stride, int len, |
| 922 | uint16_t *arr) { |
| 923 | int i; |
| 924 | uint16_t *iptr = img; |
| 925 | uint16_t *aptr = arr; |
| 926 | for (i = 0; i < len; ++i, iptr += stride) { |
| 927 | *iptr = *aptr++; |
| 928 | } |
| 929 | } |
| 930 | |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 931 | static void highbd_resize_plane(const uint8_t *const input, int height, |
| 932 | int width, int in_stride, uint8_t *output, |
| 933 | int height2, int width2, int out_stride, |
| 934 | int bd) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 935 | int i; |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 936 | uint16_t *intbuf = (uint16_t *)aom_malloc(sizeof(uint16_t) * width2 * height); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 937 | uint16_t *tmpbuf = |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 938 | (uint16_t *)aom_malloc(sizeof(uint16_t) * AOMMAX(width, height)); |
| 939 | uint16_t *arrbuf = (uint16_t *)aom_malloc(sizeof(uint16_t) * height); |
| 940 | uint16_t *arrbuf2 = (uint16_t *)aom_malloc(sizeof(uint16_t) * height2); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 941 | if (intbuf == NULL || tmpbuf == NULL || arrbuf == NULL || arrbuf2 == NULL) |
| 942 | goto Error; |
| 943 | for (i = 0; i < height; ++i) { |
| 944 | highbd_resize_multistep(CONVERT_TO_SHORTPTR(input + in_stride * i), width, |
| 945 | intbuf + width2 * i, width2, tmpbuf, bd); |
| 946 | } |
| 947 | for (i = 0; i < width2; ++i) { |
| 948 | highbd_fill_col_to_arr(intbuf + i, width2, height, arrbuf); |
| 949 | highbd_resize_multistep(arrbuf, height, arrbuf2, height2, tmpbuf, bd); |
| 950 | highbd_fill_arr_to_col(CONVERT_TO_SHORTPTR(output + i), out_stride, height2, |
| 951 | arrbuf2); |
| 952 | } |
| 953 | |
| 954 | Error: |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 955 | aom_free(intbuf); |
| 956 | aom_free(tmpbuf); |
| 957 | aom_free(arrbuf); |
| 958 | aom_free(arrbuf2); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 959 | } |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 960 | |
| 961 | #if CONFIG_FRAME_SUPERRES |
| 962 | static void highbd_upscale_normative(const uint16_t *const input, int length, |
| 963 | uint16_t *output, int olength, int bd) { |
| 964 | #if CONFIG_LOOP_RESTORATION |
| 965 | highbd_interpolate_simple(input, length, output, olength, bd); |
| 966 | #else |
| 967 | highbd_interpolate(input, length, output, olength, bd); |
| 968 | #endif // CONFIG_LOOP_RESTORATION |
| 969 | } |
| 970 | |
| 971 | static void highbd_upscale_normative_plane(const uint8_t *const input, |
| 972 | int height, int width, int in_stride, |
| 973 | uint8_t *output, int height2, |
| 974 | int width2, int out_stride, int bd) { |
| 975 | int i; |
| 976 | uint16_t *intbuf = (uint16_t *)aom_malloc(sizeof(uint16_t) * width2 * height); |
| 977 | uint16_t *arrbuf = (uint16_t *)aom_malloc(sizeof(uint16_t) * height); |
| 978 | uint16_t *arrbuf2 = (uint16_t *)aom_malloc(sizeof(uint16_t) * height2); |
| 979 | if (intbuf == NULL || arrbuf == NULL || arrbuf2 == NULL) goto Error; |
| 980 | for (i = 0; i < height; ++i) { |
| 981 | highbd_upscale_normative(CONVERT_TO_SHORTPTR(input + in_stride * i), width, |
| 982 | intbuf + width2 * i, width2, bd); |
| 983 | } |
| 984 | for (i = 0; i < width2; ++i) { |
| 985 | highbd_fill_col_to_arr(intbuf + i, width2, height, arrbuf); |
| 986 | highbd_upscale_normative(arrbuf, height, arrbuf2, height2, bd); |
| 987 | highbd_fill_arr_to_col(CONVERT_TO_SHORTPTR(output + i), out_stride, height2, |
| 988 | arrbuf2); |
| 989 | } |
| 990 | |
| 991 | Error: |
| 992 | aom_free(intbuf); |
| 993 | aom_free(arrbuf); |
| 994 | aom_free(arrbuf2); |
| 995 | } |
| 996 | #endif // CONFIG_FRAME_SUPERRES |
| 997 | |
Sebastien Alaiwan | 71e8784 | 2017-04-12 16:03:28 +0200 | [diff] [blame] | 998 | #endif // CONFIG_HIGHBITDEPTH |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 999 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 1000 | void av1_resize_frame420(const uint8_t *const y, int y_stride, |
| 1001 | const uint8_t *const u, const uint8_t *const v, |
| 1002 | int uv_stride, int height, int width, uint8_t *oy, |
| 1003 | int oy_stride, uint8_t *ou, uint8_t *ov, |
| 1004 | int ouv_stride, int oheight, int owidth) { |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 1005 | resize_plane(y, height, width, y_stride, oy, oheight, owidth, oy_stride); |
| 1006 | resize_plane(u, height / 2, width / 2, uv_stride, ou, oheight / 2, owidth / 2, |
| 1007 | ouv_stride); |
| 1008 | resize_plane(v, height / 2, width / 2, uv_stride, ov, oheight / 2, owidth / 2, |
| 1009 | ouv_stride); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 1010 | } |
| 1011 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 1012 | void av1_resize_frame422(const uint8_t *const y, int y_stride, |
| 1013 | const uint8_t *const u, const uint8_t *const v, |
| 1014 | int uv_stride, int height, int width, uint8_t *oy, |
| 1015 | int oy_stride, uint8_t *ou, uint8_t *ov, |
| 1016 | int ouv_stride, int oheight, int owidth) { |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 1017 | resize_plane(y, height, width, y_stride, oy, oheight, owidth, oy_stride); |
| 1018 | resize_plane(u, height, width / 2, uv_stride, ou, oheight, owidth / 2, |
| 1019 | ouv_stride); |
| 1020 | resize_plane(v, height, width / 2, uv_stride, ov, oheight, owidth / 2, |
| 1021 | ouv_stride); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 1022 | } |
| 1023 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 1024 | void av1_resize_frame444(const uint8_t *const y, int y_stride, |
| 1025 | const uint8_t *const u, const uint8_t *const v, |
| 1026 | int uv_stride, int height, int width, uint8_t *oy, |
| 1027 | int oy_stride, uint8_t *ou, uint8_t *ov, |
| 1028 | int ouv_stride, int oheight, int owidth) { |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 1029 | resize_plane(y, height, width, y_stride, oy, oheight, owidth, oy_stride); |
| 1030 | resize_plane(u, height, width, uv_stride, ou, oheight, owidth, ouv_stride); |
| 1031 | resize_plane(v, height, width, uv_stride, ov, oheight, owidth, ouv_stride); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 1032 | } |
| 1033 | |
Sebastien Alaiwan | 71e8784 | 2017-04-12 16:03:28 +0200 | [diff] [blame] | 1034 | #if CONFIG_HIGHBITDEPTH |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 1035 | void av1_highbd_resize_frame420(const uint8_t *const y, int y_stride, |
| 1036 | const uint8_t *const u, const uint8_t *const v, |
| 1037 | int uv_stride, int height, int width, |
| 1038 | uint8_t *oy, int oy_stride, uint8_t *ou, |
| 1039 | uint8_t *ov, int ouv_stride, int oheight, |
| 1040 | int owidth, int bd) { |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 1041 | highbd_resize_plane(y, height, width, y_stride, oy, oheight, owidth, |
| 1042 | oy_stride, bd); |
| 1043 | highbd_resize_plane(u, height / 2, width / 2, uv_stride, ou, oheight / 2, |
| 1044 | owidth / 2, ouv_stride, bd); |
| 1045 | highbd_resize_plane(v, height / 2, width / 2, uv_stride, ov, oheight / 2, |
| 1046 | owidth / 2, ouv_stride, bd); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 1047 | } |
| 1048 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 1049 | void av1_highbd_resize_frame422(const uint8_t *const y, int y_stride, |
| 1050 | const uint8_t *const u, const uint8_t *const v, |
| 1051 | int uv_stride, int height, int width, |
| 1052 | uint8_t *oy, int oy_stride, uint8_t *ou, |
| 1053 | uint8_t *ov, int ouv_stride, int oheight, |
| 1054 | int owidth, int bd) { |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 1055 | highbd_resize_plane(y, height, width, y_stride, oy, oheight, owidth, |
| 1056 | oy_stride, bd); |
| 1057 | highbd_resize_plane(u, height, width / 2, uv_stride, ou, oheight, owidth / 2, |
| 1058 | ouv_stride, bd); |
| 1059 | highbd_resize_plane(v, height, width / 2, uv_stride, ov, oheight, owidth / 2, |
| 1060 | ouv_stride, bd); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 1061 | } |
| 1062 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 1063 | void av1_highbd_resize_frame444(const uint8_t *const y, int y_stride, |
| 1064 | const uint8_t *const u, const uint8_t *const v, |
| 1065 | int uv_stride, int height, int width, |
| 1066 | uint8_t *oy, int oy_stride, uint8_t *ou, |
| 1067 | uint8_t *ov, int ouv_stride, int oheight, |
| 1068 | int owidth, int bd) { |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 1069 | highbd_resize_plane(y, height, width, y_stride, oy, oheight, owidth, |
| 1070 | oy_stride, bd); |
| 1071 | highbd_resize_plane(u, height, width, uv_stride, ou, oheight, owidth, |
| 1072 | ouv_stride, bd); |
| 1073 | highbd_resize_plane(v, height, width, uv_stride, ov, oheight, owidth, |
| 1074 | ouv_stride, bd); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 1075 | } |
Sebastien Alaiwan | 71e8784 | 2017-04-12 16:03:28 +0200 | [diff] [blame] | 1076 | #endif // CONFIG_HIGHBITDEPTH |
Fergus Simpson | 090bb60 | 2017-04-07 12:37:53 -0700 | [diff] [blame] | 1077 | |
| 1078 | #if CONFIG_HIGHBITDEPTH |
Fergus Simpson | d2bcbb5 | 2017-05-22 23:15:05 -0700 | [diff] [blame] | 1079 | void av1_resize_and_extend_frame(const YV12_BUFFER_CONFIG *src, |
| 1080 | YV12_BUFFER_CONFIG *dst, int bd) { |
Fergus Simpson | 090bb60 | 2017-04-07 12:37:53 -0700 | [diff] [blame] | 1081 | #else |
Fergus Simpson | d2bcbb5 | 2017-05-22 23:15:05 -0700 | [diff] [blame] | 1082 | void av1_resize_and_extend_frame(const YV12_BUFFER_CONFIG *src, |
| 1083 | YV12_BUFFER_CONFIG *dst) { |
Fergus Simpson | 090bb60 | 2017-04-07 12:37:53 -0700 | [diff] [blame] | 1084 | #endif // CONFIG_HIGHBITDEPTH |
| 1085 | // TODO(dkovalev): replace YV12_BUFFER_CONFIG with aom_image_t |
| 1086 | int i; |
| 1087 | const uint8_t *const srcs[3] = { src->y_buffer, src->u_buffer, |
| 1088 | src->v_buffer }; |
| 1089 | const int src_strides[3] = { src->y_stride, src->uv_stride, src->uv_stride }; |
| 1090 | const int src_widths[3] = { src->y_crop_width, src->uv_crop_width, |
| 1091 | src->uv_crop_width }; |
| 1092 | const int src_heights[3] = { src->y_crop_height, src->uv_crop_height, |
| 1093 | src->uv_crop_height }; |
| 1094 | uint8_t *const dsts[3] = { dst->y_buffer, dst->u_buffer, dst->v_buffer }; |
| 1095 | const int dst_strides[3] = { dst->y_stride, dst->uv_stride, dst->uv_stride }; |
| 1096 | const int dst_widths[3] = { dst->y_crop_width, dst->uv_crop_width, |
| 1097 | dst->uv_crop_width }; |
| 1098 | const int dst_heights[3] = { dst->y_crop_height, dst->uv_crop_height, |
| 1099 | dst->uv_crop_height }; |
| 1100 | |
| 1101 | for (i = 0; i < MAX_MB_PLANE; ++i) { |
| 1102 | #if CONFIG_HIGHBITDEPTH |
| 1103 | if (src->flags & YV12_FLAG_HIGHBITDEPTH) |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 1104 | highbd_resize_plane(srcs[i], src_heights[i], src_widths[i], |
| 1105 | src_strides[i], dsts[i], dst_heights[i], |
| 1106 | dst_widths[i], dst_strides[i], bd); |
Fergus Simpson | 090bb60 | 2017-04-07 12:37:53 -0700 | [diff] [blame] | 1107 | else |
| 1108 | #endif // CONFIG_HIGHBITDEPTH |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 1109 | resize_plane(srcs[i], src_heights[i], src_widths[i], src_strides[i], |
| 1110 | dsts[i], dst_heights[i], dst_widths[i], dst_strides[i]); |
Fergus Simpson | 090bb60 | 2017-04-07 12:37:53 -0700 | [diff] [blame] | 1111 | } |
| 1112 | aom_extend_frame_borders(dst); |
| 1113 | } |
| 1114 | |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 1115 | #if CONFIG_FRAME_SUPERRES |
| 1116 | #if CONFIG_HIGHBITDEPTH |
| 1117 | void av1_upscale_normative_and_extend_frame(const YV12_BUFFER_CONFIG *src, |
| 1118 | YV12_BUFFER_CONFIG *dst, int bd) { |
| 1119 | #else |
| 1120 | void av1_upscale_normative_and_extend_frame(const YV12_BUFFER_CONFIG *src, |
| 1121 | YV12_BUFFER_CONFIG *dst) { |
| 1122 | #endif // CONFIG_HIGHBITDEPTH |
| 1123 | // TODO(dkovalev): replace YV12_BUFFER_CONFIG with aom_image_t |
| 1124 | int i; |
| 1125 | const uint8_t *const srcs[3] = { src->y_buffer, src->u_buffer, |
| 1126 | src->v_buffer }; |
| 1127 | const int src_strides[3] = { src->y_stride, src->uv_stride, src->uv_stride }; |
| 1128 | const int src_widths[3] = { src->y_crop_width, src->uv_crop_width, |
| 1129 | src->uv_crop_width }; |
| 1130 | const int src_heights[3] = { src->y_crop_height, src->uv_crop_height, |
| 1131 | src->uv_crop_height }; |
| 1132 | uint8_t *const dsts[3] = { dst->y_buffer, dst->u_buffer, dst->v_buffer }; |
| 1133 | const int dst_strides[3] = { dst->y_stride, dst->uv_stride, dst->uv_stride }; |
| 1134 | const int dst_widths[3] = { dst->y_crop_width, dst->uv_crop_width, |
| 1135 | dst->uv_crop_width }; |
| 1136 | const int dst_heights[3] = { dst->y_crop_height, dst->uv_crop_height, |
| 1137 | dst->uv_crop_height }; |
| 1138 | |
| 1139 | for (i = 0; i < MAX_MB_PLANE; ++i) { |
| 1140 | #if CONFIG_HIGHBITDEPTH |
| 1141 | if (src->flags & YV12_FLAG_HIGHBITDEPTH) |
| 1142 | highbd_upscale_normative_plane(srcs[i], src_heights[i], src_widths[i], |
| 1143 | src_strides[i], dsts[i], dst_heights[i], |
| 1144 | dst_widths[i], dst_strides[i], bd); |
| 1145 | else |
| 1146 | #endif // CONFIG_HIGHBITDEPTH |
| 1147 | upscale_normative_plane(srcs[i], src_heights[i], src_widths[i], |
| 1148 | src_strides[i], dsts[i], dst_heights[i], |
| 1149 | dst_widths[i], dst_strides[i]); |
Fergus Simpson | 090bb60 | 2017-04-07 12:37:53 -0700 | [diff] [blame] | 1150 | } |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 1151 | aom_extend_frame_borders(dst); |
Fergus Simpson | 090bb60 | 2017-04-07 12:37:53 -0700 | [diff] [blame] | 1152 | } |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 1153 | #endif // CONFIG_FRAME_SUPERRES |
Fergus Simpson | 090bb60 | 2017-04-07 12:37:53 -0700 | [diff] [blame] | 1154 | |
| 1155 | YV12_BUFFER_CONFIG *av1_scale_if_required(AV1_COMMON *cm, |
| 1156 | YV12_BUFFER_CONFIG *unscaled, |
| 1157 | YV12_BUFFER_CONFIG *scaled) { |
Fergus Simpson | d2bcbb5 | 2017-05-22 23:15:05 -0700 | [diff] [blame] | 1158 | if (cm->width != unscaled->y_crop_width || |
| 1159 | cm->height != unscaled->y_crop_height) { |
Fergus Simpson | 090bb60 | 2017-04-07 12:37:53 -0700 | [diff] [blame] | 1160 | #if CONFIG_HIGHBITDEPTH |
Fergus Simpson | d2bcbb5 | 2017-05-22 23:15:05 -0700 | [diff] [blame] | 1161 | av1_resize_and_extend_frame(unscaled, scaled, (int)cm->bit_depth); |
Fergus Simpson | 090bb60 | 2017-04-07 12:37:53 -0700 | [diff] [blame] | 1162 | #else |
Fergus Simpson | d2bcbb5 | 2017-05-22 23:15:05 -0700 | [diff] [blame] | 1163 | av1_resize_and_extend_frame(unscaled, scaled); |
Fergus Simpson | 090bb60 | 2017-04-07 12:37:53 -0700 | [diff] [blame] | 1164 | #endif // CONFIG_HIGHBITDEPTH |
| 1165 | return scaled; |
| 1166 | } else { |
| 1167 | return unscaled; |
| 1168 | } |
| 1169 | } |
Fergus Simpson | d2bcbb5 | 2017-05-22 23:15:05 -0700 | [diff] [blame] | 1170 | |
Fergus Simpson | bfbf6a5 | 2017-06-14 23:13:12 -0700 | [diff] [blame] | 1171 | void av1_calculate_scaled_size(int *width, int *height, int num) { |
Fergus Simpson | 505f006 | 2017-06-27 11:23:34 -0700 | [diff] [blame] | 1172 | if (num != SCALE_DENOMINATOR) { |
| 1173 | *width = *width * num / SCALE_DENOMINATOR; |
| 1174 | *height = *height * num / SCALE_DENOMINATOR; |
| 1175 | // Make width and height even |
| 1176 | *width += *width & 1; |
| 1177 | *height += *height & 1; |
| 1178 | } |
Fergus Simpson | d2bcbb5 | 2017-05-22 23:15:05 -0700 | [diff] [blame] | 1179 | } |
| 1180 | |
Debargha Mukherjee | 29e40a6 | 2017-06-14 09:37:12 -0700 | [diff] [blame] | 1181 | #if CONFIG_FRAME_SUPERRES |
Fergus Simpson | d2bcbb5 | 2017-05-22 23:15:05 -0700 | [diff] [blame] | 1182 | // TODO(afergs): Look for in-place upscaling |
| 1183 | // TODO(afergs): aom_ vs av1_ functions? Which can I use? |
| 1184 | // Upscale decoded image. |
| 1185 | void av1_superres_upscale(AV1_COMMON *cm, BufferPool *const pool) { |
| 1186 | if (av1_superres_unscaled(cm)) return; |
| 1187 | |
| 1188 | YV12_BUFFER_CONFIG copy_buffer; |
| 1189 | memset(©_buffer, 0, sizeof(copy_buffer)); |
| 1190 | |
| 1191 | YV12_BUFFER_CONFIG *const frame_to_show = get_frame_new_buffer(cm); |
| 1192 | |
| 1193 | if (aom_alloc_frame_buffer(©_buffer, cm->width, cm->height, |
| 1194 | cm->subsampling_x, cm->subsampling_y, |
David Barker | 2676235 | 2017-06-13 14:11:39 +0100 | [diff] [blame] | 1195 | #if CONFIG_HIGHBITDEPTH |
Fergus Simpson | d2bcbb5 | 2017-05-22 23:15:05 -0700 | [diff] [blame] | 1196 | cm->use_highbitdepth, |
| 1197 | #endif // CONFIG_HIGHBITDEPTH |
| 1198 | AOM_BORDER_IN_PIXELS, cm->byte_alignment)) |
| 1199 | aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR, |
| 1200 | "Failed to allocate copy buffer for superres upscaling"); |
| 1201 | |
| 1202 | // Copy function assumes the frames are the same size, doesn't copy bit_depth. |
| 1203 | aom_yv12_copy_frame(frame_to_show, ©_buffer); |
| 1204 | copy_buffer.bit_depth = frame_to_show->bit_depth; |
| 1205 | assert(copy_buffer.y_crop_width == cm->width); |
| 1206 | assert(copy_buffer.y_crop_height == cm->height); |
| 1207 | |
| 1208 | // Realloc the current frame buffer at a higher resolution in place. |
| 1209 | if (pool != NULL) { |
| 1210 | // Use callbacks if on the decoder. |
| 1211 | aom_codec_frame_buffer_t *fb = |
| 1212 | &pool->frame_bufs[cm->new_fb_idx].raw_frame_buffer; |
| 1213 | aom_release_frame_buffer_cb_fn_t release_fb_cb = pool->release_fb_cb; |
| 1214 | aom_get_frame_buffer_cb_fn_t cb = pool->get_fb_cb; |
| 1215 | void *cb_priv = pool->cb_priv; |
| 1216 | |
| 1217 | // Realloc with callback does not release the frame buffer - release first. |
| 1218 | if (release_fb_cb(cb_priv, fb)) |
| 1219 | aom_internal_error( |
| 1220 | &cm->error, AOM_CODEC_MEM_ERROR, |
| 1221 | "Failed to free current frame buffer before superres upscaling"); |
| 1222 | |
| 1223 | if (aom_realloc_frame_buffer( |
| 1224 | frame_to_show, cm->superres_upscaled_width, |
| 1225 | cm->superres_upscaled_height, cm->subsampling_x, cm->subsampling_y, |
David Barker | 2676235 | 2017-06-13 14:11:39 +0100 | [diff] [blame] | 1226 | #if CONFIG_HIGHBITDEPTH |
Fergus Simpson | d2bcbb5 | 2017-05-22 23:15:05 -0700 | [diff] [blame] | 1227 | cm->use_highbitdepth, |
| 1228 | #endif // CONFIG_HIGHBITDEPTH |
| 1229 | AOM_BORDER_IN_PIXELS, cm->byte_alignment, fb, cb, cb_priv)) |
| 1230 | aom_internal_error( |
| 1231 | &cm->error, AOM_CODEC_MEM_ERROR, |
| 1232 | "Failed to allocate current frame buffer for superres upscaling"); |
| 1233 | } else { |
| 1234 | // Don't use callbacks on the encoder. |
| 1235 | if (aom_alloc_frame_buffer(frame_to_show, cm->superres_upscaled_width, |
| 1236 | cm->superres_upscaled_height, cm->subsampling_x, |
| 1237 | cm->subsampling_y, |
David Barker | 2676235 | 2017-06-13 14:11:39 +0100 | [diff] [blame] | 1238 | #if CONFIG_HIGHBITDEPTH |
Fergus Simpson | d2bcbb5 | 2017-05-22 23:15:05 -0700 | [diff] [blame] | 1239 | cm->use_highbitdepth, |
| 1240 | #endif // CONFIG_HIGHBITDEPTH |
| 1241 | AOM_BORDER_IN_PIXELS, cm->byte_alignment)) |
| 1242 | aom_internal_error( |
| 1243 | &cm->error, AOM_CODEC_MEM_ERROR, |
| 1244 | "Failed to reallocate current frame buffer for superres upscaling"); |
| 1245 | } |
| 1246 | // TODO(afergs): verify frame_to_show is correct after realloc |
| 1247 | // encoder: |
| 1248 | // decoder: |
| 1249 | frame_to_show->bit_depth = copy_buffer.bit_depth; |
| 1250 | assert(frame_to_show->y_crop_width == cm->superres_upscaled_width); |
| 1251 | assert(frame_to_show->y_crop_height == cm->superres_upscaled_height); |
| 1252 | |
| 1253 | // Scale up and back into frame_to_show. |
| 1254 | assert(frame_to_show->y_crop_width != cm->width); |
| 1255 | assert(frame_to_show->y_crop_height != cm->height); |
| 1256 | #if CONFIG_HIGHBITDEPTH |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 1257 | av1_upscale_normative_and_extend_frame(©_buffer, frame_to_show, |
| 1258 | (int)cm->bit_depth); |
Fergus Simpson | d2bcbb5 | 2017-05-22 23:15:05 -0700 | [diff] [blame] | 1259 | #else |
Debargha Mukherjee | 3897e2d | 2017-08-17 14:48:04 -0700 | [diff] [blame] | 1260 | av1_upscale_normative_and_extend_frame(©_buffer, frame_to_show); |
Fergus Simpson | d2bcbb5 | 2017-05-22 23:15:05 -0700 | [diff] [blame] | 1261 | #endif // CONFIG_HIGHBITDEPTH |
| 1262 | |
| 1263 | // Free the copy buffer |
| 1264 | aom_free_frame_buffer(©_buffer); |
| 1265 | } |
| 1266 | #endif // CONFIG_FRAME_SUPERRES |