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 | |
James Zern | e1cbb13 | 2018-08-22 14:10:36 -0700 | [diff] [blame] | 12 | #ifndef AOM_AV1_COMMON_FILTER_H_ |
| 13 | #define AOM_AV1_COMMON_FILTER_H_ |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 14 | |
Rupert Swarbrick | 27e9029 | 2017-09-28 17:46:50 +0100 | [diff] [blame] | 15 | #include <assert.h> |
| 16 | |
Tom Finegan | 60e653d | 2018-05-22 11:34:58 -0700 | [diff] [blame] | 17 | #include "config/aom_config.h" |
| 18 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 19 | #include "aom/aom_integer.h" |
| 20 | #include "aom_dsp/aom_filter.h" |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 21 | #include "aom_ports/mem.h" |
| 22 | |
| 23 | #ifdef __cplusplus |
| 24 | extern "C" { |
| 25 | #endif |
| 26 | |
Yunqing Wang | 3ec11d1 | 2018-01-05 12:45:08 -0800 | [diff] [blame] | 27 | #define MAX_FILTER_TAP 8 |
Jingning Han | b14c179 | 2017-04-20 15:10:29 -0700 | [diff] [blame] | 28 | |
Urvang Joshi | f5f5c84 | 2017-10-19 16:17:54 -0700 | [diff] [blame] | 29 | typedef enum ATTRIBUTE_PACKED { |
Urvang Joshi | a9b174b | 2017-02-17 11:50:12 -0800 | [diff] [blame] | 30 | EIGHTTAP_REGULAR, |
| 31 | EIGHTTAP_SMOOTH, |
Thomas Davies | ec92c11 | 2017-09-25 11:03:58 +0100 | [diff] [blame] | 32 | MULTITAP_SHARP, |
Urvang Joshi | a9b174b | 2017-02-17 11:50:12 -0800 | [diff] [blame] | 33 | BILINEAR, |
Urvang Joshi | a9b174b | 2017-02-17 11:50:12 -0800 | [diff] [blame] | 34 | INTERP_FILTERS_ALL, |
| 35 | SWITCHABLE_FILTERS = BILINEAR, |
| 36 | SWITCHABLE = SWITCHABLE_FILTERS + 1, /* the last switchable one */ |
| 37 | EXTRA_FILTERS = INTERP_FILTERS_ALL - SWITCHABLE_FILTERS, |
Urvang Joshi | a9b174b | 2017-02-17 11:50:12 -0800 | [diff] [blame] | 38 | } InterpFilter; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 39 | |
Satish Kumar Suman | 4667aa1 | 2018-12-14 18:28:19 +0530 | [diff] [blame] | 40 | enum { |
Yunqing Wang | 91c9b2e | 2018-09-11 16:13:49 -0700 | [diff] [blame] | 41 | USE_2_TAPS_ORIG = 0, // This is used in temporal filtering. |
| 42 | USE_2_TAPS, |
| 43 | USE_4_TAPS, |
| 44 | USE_8_TAPS, |
Satish Kumar Suman | 4667aa1 | 2018-12-14 18:28:19 +0530 | [diff] [blame] | 45 | } UENUM1BYTE(SUBPEL_SEARCH_TYPE); |
Yunqing Wang | 91c9b2e | 2018-09-11 16:13:49 -0700 | [diff] [blame] | 46 | |
Yue Chen | e6fefb5 | 2018-10-24 16:23:39 -0700 | [diff] [blame] | 47 | // Pack two InterpFilter's into a uint32_t: since there are at most 10 filters, |
| 48 | // we can use 16 bits for each and have more than enough space. This reduces |
| 49 | // argument passing and unifies the operation of setting a (pair of) filters. |
Rupert Swarbrick | 27e9029 | 2017-09-28 17:46:50 +0100 | [diff] [blame] | 50 | typedef uint32_t InterpFilters; |
| 51 | static INLINE InterpFilter av1_extract_interp_filter(InterpFilters filters, |
| 52 | int x_filter) { |
Venkat | 06e800c | 2018-06-12 17:49:04 +0530 | [diff] [blame] | 53 | return (InterpFilter)((filters >> (x_filter ? 16 : 0)) & 0xf); |
Rupert Swarbrick | 27e9029 | 2017-09-28 17:46:50 +0100 | [diff] [blame] | 54 | } |
| 55 | |
| 56 | static INLINE InterpFilters av1_make_interp_filters(InterpFilter y_filter, |
| 57 | InterpFilter x_filter) { |
Venkat | 06e800c | 2018-06-12 17:49:04 +0530 | [diff] [blame] | 58 | uint16_t y16 = y_filter & 0xf; |
| 59 | uint16_t x16 = x_filter & 0xf; |
Rupert Swarbrick | 27e9029 | 2017-09-28 17:46:50 +0100 | [diff] [blame] | 60 | return y16 | ((uint32_t)x16 << 16); |
| 61 | } |
| 62 | |
| 63 | static INLINE InterpFilters av1_broadcast_interp_filter(InterpFilter filter) { |
| 64 | return av1_make_interp_filters(filter, filter); |
| 65 | } |
Rupert Swarbrick | 27e9029 | 2017-09-28 17:46:50 +0100 | [diff] [blame] | 66 | |
| 67 | static INLINE InterpFilter av1_unswitchable_filter(InterpFilter filter) { |
| 68 | return filter == SWITCHABLE ? EIGHTTAP_REGULAR : filter; |
| 69 | } |
| 70 | |
Peng Bin | 3a0c2ed | 2018-07-19 16:24:00 +0800 | [diff] [blame] | 71 | /* (1 << LOG_SWITCHABLE_FILTERS) > SWITCHABLE_FILTERS */ |
| 72 | #define LOG_SWITCHABLE_FILTERS 2 |
Frederic Barbier | 7b35d73 | 2017-07-11 17:32:39 +0200 | [diff] [blame] | 73 | |
Frederic Barbier | 7b35d73 | 2017-07-11 17:32:39 +0200 | [diff] [blame] | 74 | #define MAX_SUBPEL_TAPS 12 |
Angie Chiang | 1733f6b | 2017-01-05 09:52:20 -0800 | [diff] [blame] | 75 | #define SWITCHABLE_FILTER_CONTEXTS ((SWITCHABLE_FILTERS + 1) * 4) |
| 76 | #define INTER_FILTER_COMP_OFFSET (SWITCHABLE_FILTERS + 1) |
| 77 | #define INTER_FILTER_DIR_OFFSET ((SWITCHABLE_FILTERS + 1) * 2) |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 78 | |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 79 | typedef struct InterpFilterParams { |
| 80 | const int16_t *filter_ptr; |
| 81 | uint16_t taps; |
| 82 | uint16_t subpel_shifts; |
Angie Chiang | b9ba5c2 | 2016-10-03 16:39:27 -0700 | [diff] [blame] | 83 | InterpFilter interp_filter; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 84 | } InterpFilterParams; |
| 85 | |
Peng Bin | 3a0c2ed | 2018-07-19 16:24:00 +0800 | [diff] [blame] | 86 | DECLARE_ALIGNED(256, static const InterpKernel, |
| 87 | av1_bilinear_filters[SUBPEL_SHIFTS]) = { |
| 88 | { 0, 0, 0, 128, 0, 0, 0, 0 }, { 0, 0, 0, 120, 8, 0, 0, 0 }, |
| 89 | { 0, 0, 0, 112, 16, 0, 0, 0 }, { 0, 0, 0, 104, 24, 0, 0, 0 }, |
| 90 | { 0, 0, 0, 96, 32, 0, 0, 0 }, { 0, 0, 0, 88, 40, 0, 0, 0 }, |
| 91 | { 0, 0, 0, 80, 48, 0, 0, 0 }, { 0, 0, 0, 72, 56, 0, 0, 0 }, |
| 92 | { 0, 0, 0, 64, 64, 0, 0, 0 }, { 0, 0, 0, 56, 72, 0, 0, 0 }, |
| 93 | { 0, 0, 0, 48, 80, 0, 0, 0 }, { 0, 0, 0, 40, 88, 0, 0, 0 }, |
| 94 | { 0, 0, 0, 32, 96, 0, 0, 0 }, { 0, 0, 0, 24, 104, 0, 0, 0 }, |
| 95 | { 0, 0, 0, 16, 112, 0, 0, 0 }, { 0, 0, 0, 8, 120, 0, 0, 0 } |
| 96 | }; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 97 | |
Peng Bin | 3a0c2ed | 2018-07-19 16:24:00 +0800 | [diff] [blame] | 98 | DECLARE_ALIGNED(256, static const InterpKernel, |
| 99 | av1_sub_pel_filters_8[SUBPEL_SHIFTS]) = { |
| 100 | { 0, 0, 0, 128, 0, 0, 0, 0 }, { 0, 2, -6, 126, 8, -2, 0, 0 }, |
| 101 | { 0, 2, -10, 122, 18, -4, 0, 0 }, { 0, 2, -12, 116, 28, -8, 2, 0 }, |
| 102 | { 0, 2, -14, 110, 38, -10, 2, 0 }, { 0, 2, -14, 102, 48, -12, 2, 0 }, |
| 103 | { 0, 2, -16, 94, 58, -12, 2, 0 }, { 0, 2, -14, 84, 66, -12, 2, 0 }, |
| 104 | { 0, 2, -14, 76, 76, -14, 2, 0 }, { 0, 2, -12, 66, 84, -14, 2, 0 }, |
| 105 | { 0, 2, -12, 58, 94, -16, 2, 0 }, { 0, 2, -12, 48, 102, -14, 2, 0 }, |
| 106 | { 0, 2, -10, 38, 110, -14, 2, 0 }, { 0, 2, -8, 28, 116, -12, 2, 0 }, |
| 107 | { 0, 0, -4, 18, 122, -10, 2, 0 }, { 0, 0, -2, 8, 126, -6, 2, 0 } |
| 108 | }; |
| 109 | |
| 110 | DECLARE_ALIGNED(256, static const InterpKernel, |
| 111 | av1_sub_pel_filters_8sharp[SUBPEL_SHIFTS]) = { |
| 112 | { 0, 0, 0, 128, 0, 0, 0, 0 }, { -2, 2, -6, 126, 8, -2, 2, 0 }, |
| 113 | { -2, 6, -12, 124, 16, -6, 4, -2 }, { -2, 8, -18, 120, 26, -10, 6, -2 }, |
| 114 | { -4, 10, -22, 116, 38, -14, 6, -2 }, { -4, 10, -22, 108, 48, -18, 8, -2 }, |
| 115 | { -4, 10, -24, 100, 60, -20, 8, -2 }, { -4, 10, -24, 90, 70, -22, 10, -2 }, |
| 116 | { -4, 12, -24, 80, 80, -24, 12, -4 }, { -2, 10, -22, 70, 90, -24, 10, -4 }, |
| 117 | { -2, 8, -20, 60, 100, -24, 10, -4 }, { -2, 8, -18, 48, 108, -22, 10, -4 }, |
| 118 | { -2, 6, -14, 38, 116, -22, 10, -4 }, { -2, 6, -10, 26, 120, -18, 8, -2 }, |
| 119 | { -2, 4, -6, 16, 124, -12, 6, -2 }, { 0, 2, -2, 8, 126, -6, 2, -2 } |
| 120 | }; |
| 121 | |
| 122 | DECLARE_ALIGNED(256, static const InterpKernel, |
| 123 | av1_sub_pel_filters_8smooth[SUBPEL_SHIFTS]) = { |
| 124 | { 0, 0, 0, 128, 0, 0, 0, 0 }, { 0, 2, 28, 62, 34, 2, 0, 0 }, |
| 125 | { 0, 0, 26, 62, 36, 4, 0, 0 }, { 0, 0, 22, 62, 40, 4, 0, 0 }, |
| 126 | { 0, 0, 20, 60, 42, 6, 0, 0 }, { 0, 0, 18, 58, 44, 8, 0, 0 }, |
| 127 | { 0, 0, 16, 56, 46, 10, 0, 0 }, { 0, -2, 16, 54, 48, 12, 0, 0 }, |
| 128 | { 0, -2, 14, 52, 52, 14, -2, 0 }, { 0, 0, 12, 48, 54, 16, -2, 0 }, |
| 129 | { 0, 0, 10, 46, 56, 16, 0, 0 }, { 0, 0, 8, 44, 58, 18, 0, 0 }, |
| 130 | { 0, 0, 6, 42, 60, 20, 0, 0 }, { 0, 0, 4, 40, 62, 22, 0, 0 }, |
| 131 | { 0, 0, 4, 36, 62, 26, 0, 0 }, { 0, 0, 2, 34, 62, 28, 2, 0 } |
| 132 | }; |
| 133 | |
| 134 | static const InterpFilterParams |
| 135 | av1_interp_filter_params_list[SWITCHABLE_FILTERS + 1] = { |
| 136 | { (const int16_t *)av1_sub_pel_filters_8, SUBPEL_TAPS, SUBPEL_SHIFTS, |
| 137 | EIGHTTAP_REGULAR }, |
| 138 | { (const int16_t *)av1_sub_pel_filters_8smooth, SUBPEL_TAPS, |
| 139 | SUBPEL_SHIFTS, EIGHTTAP_SMOOTH }, |
| 140 | { (const int16_t *)av1_sub_pel_filters_8sharp, SUBPEL_TAPS, SUBPEL_SHIFTS, |
| 141 | MULTITAP_SHARP }, |
| 142 | { (const int16_t *)av1_bilinear_filters, SUBPEL_TAPS, SUBPEL_SHIFTS, |
| 143 | BILINEAR } |
| 144 | }; |
| 145 | |
Hui Su | d547fa6 | 2018-09-06 16:13:58 -0700 | [diff] [blame] | 146 | // A special 2-tap bilinear filter for IntraBC chroma. IntraBC uses full pixel |
| 147 | // MV for luma. If sub-sampling exists, chroma may possibly use half-pel MV. |
| 148 | DECLARE_ALIGNED(256, static const int16_t, av1_intrabc_bilinear_filter[2]) = { |
| 149 | 64, |
| 150 | 64, |
| 151 | }; |
| 152 | |
| 153 | static const InterpFilterParams av1_intrabc_filter_params = { |
| 154 | av1_intrabc_bilinear_filter, 2, 0, BILINEAR |
| 155 | }; |
| 156 | |
Peng Bin | 3a0c2ed | 2018-07-19 16:24:00 +0800 | [diff] [blame] | 157 | DECLARE_ALIGNED(256, static const InterpKernel, |
| 158 | av1_sub_pel_filters_4[SUBPEL_SHIFTS]) = { |
| 159 | { 0, 0, 0, 128, 0, 0, 0, 0 }, { 0, 0, -4, 126, 8, -2, 0, 0 }, |
| 160 | { 0, 0, -8, 122, 18, -4, 0, 0 }, { 0, 0, -10, 116, 28, -6, 0, 0 }, |
| 161 | { 0, 0, -12, 110, 38, -8, 0, 0 }, { 0, 0, -12, 102, 48, -10, 0, 0 }, |
| 162 | { 0, 0, -14, 94, 58, -10, 0, 0 }, { 0, 0, -12, 84, 66, -10, 0, 0 }, |
| 163 | { 0, 0, -12, 76, 76, -12, 0, 0 }, { 0, 0, -10, 66, 84, -12, 0, 0 }, |
| 164 | { 0, 0, -10, 58, 94, -14, 0, 0 }, { 0, 0, -10, 48, 102, -12, 0, 0 }, |
| 165 | { 0, 0, -8, 38, 110, -12, 0, 0 }, { 0, 0, -6, 28, 116, -10, 0, 0 }, |
| 166 | { 0, 0, -4, 18, 122, -8, 0, 0 }, { 0, 0, -2, 8, 126, -4, 0, 0 } |
| 167 | }; |
| 168 | DECLARE_ALIGNED(256, static const InterpKernel, |
| 169 | av1_sub_pel_filters_4smooth[SUBPEL_SHIFTS]) = { |
| 170 | { 0, 0, 0, 128, 0, 0, 0, 0 }, { 0, 0, 30, 62, 34, 2, 0, 0 }, |
| 171 | { 0, 0, 26, 62, 36, 4, 0, 0 }, { 0, 0, 22, 62, 40, 4, 0, 0 }, |
| 172 | { 0, 0, 20, 60, 42, 6, 0, 0 }, { 0, 0, 18, 58, 44, 8, 0, 0 }, |
| 173 | { 0, 0, 16, 56, 46, 10, 0, 0 }, { 0, 0, 14, 54, 48, 12, 0, 0 }, |
| 174 | { 0, 0, 12, 52, 52, 12, 0, 0 }, { 0, 0, 12, 48, 54, 14, 0, 0 }, |
| 175 | { 0, 0, 10, 46, 56, 16, 0, 0 }, { 0, 0, 8, 44, 58, 18, 0, 0 }, |
| 176 | { 0, 0, 6, 42, 60, 20, 0, 0 }, { 0, 0, 4, 40, 62, 22, 0, 0 }, |
| 177 | { 0, 0, 4, 36, 62, 26, 0, 0 }, { 0, 0, 2, 34, 62, 30, 0, 0 } |
| 178 | }; |
| 179 | |
| 180 | // For w<=4, MULTITAP_SHARP is the same as EIGHTTAP_REGULAR |
| 181 | static const InterpFilterParams av1_interp_4tap[SWITCHABLE_FILTERS + 1] = { |
| 182 | { (const int16_t *)av1_sub_pel_filters_4, SUBPEL_TAPS, SUBPEL_SHIFTS, |
| 183 | EIGHTTAP_REGULAR }, |
| 184 | { (const int16_t *)av1_sub_pel_filters_4smooth, SUBPEL_TAPS, SUBPEL_SHIFTS, |
| 185 | EIGHTTAP_SMOOTH }, |
| 186 | { (const int16_t *)av1_sub_pel_filters_4, SUBPEL_TAPS, SUBPEL_SHIFTS, |
| 187 | EIGHTTAP_REGULAR }, |
| 188 | { (const int16_t *)av1_bilinear_filters, SUBPEL_TAPS, SUBPEL_SHIFTS, |
| 189 | BILINEAR }, |
| 190 | }; |
| 191 | |
| 192 | static INLINE const InterpFilterParams * |
| 193 | av1_get_interp_filter_params_with_block_size(const InterpFilter interp_filter, |
| 194 | const int w) { |
| 195 | if (w <= 4) return &av1_interp_4tap[interp_filter]; |
| 196 | return &av1_interp_filter_params_list[interp_filter]; |
| 197 | } |
| 198 | |
Yunqing Wang | 91c9b2e | 2018-09-11 16:13:49 -0700 | [diff] [blame] | 199 | static INLINE const InterpFilterParams *get_4tap_interp_filter_params( |
Yunqing Wang | 901ecab | 2018-08-06 12:27:24 -0700 | [diff] [blame] | 200 | const InterpFilter interp_filter) { |
| 201 | return &av1_interp_4tap[interp_filter]; |
| 202 | } |
| 203 | |
Peng Bin | 3a0c2ed | 2018-07-19 16:24:00 +0800 | [diff] [blame] | 204 | static INLINE const int16_t *av1_get_interp_filter_kernel( |
Sachin Kumar Garg | 8048e8c | 2018-10-10 18:48:44 +0530 | [diff] [blame] | 205 | const InterpFilter interp_filter, int subpel_search) { |
| 206 | assert(subpel_search >= USE_2_TAPS); |
| 207 | return (subpel_search == USE_2_TAPS) |
| 208 | ? av1_interp_4tap[BILINEAR].filter_ptr |
| 209 | : ((subpel_search == USE_4_TAPS) |
| 210 | ? av1_interp_4tap[interp_filter].filter_ptr |
| 211 | : av1_interp_filter_params_list[interp_filter].filter_ptr); |
Peng Bin | 3a0c2ed | 2018-07-19 16:24:00 +0800 | [diff] [blame] | 212 | } |
Zhijie Yang | f02f8ae | 2017-10-26 17:58:29 -0700 | [diff] [blame] | 213 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 214 | static INLINE const int16_t *av1_get_interp_filter_subpel_kernel( |
Peng Bin | 3a0c2ed | 2018-07-19 16:24:00 +0800 | [diff] [blame] | 215 | const InterpFilterParams *const filter_params, const int subpel) { |
| 216 | return filter_params->filter_ptr + filter_params->taps * subpel; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 217 | } |
| 218 | |
Yunqing Wang | 91c9b2e | 2018-09-11 16:13:49 -0700 | [diff] [blame] | 219 | static INLINE const InterpFilterParams *av1_get_filter(int subpel_search) { |
| 220 | assert(subpel_search >= USE_2_TAPS); |
Yunqing Wang | dca41c0 | 2018-10-29 15:39:07 -0700 | [diff] [blame] | 221 | |
| 222 | switch (subpel_search) { |
| 223 | case USE_2_TAPS: return get_4tap_interp_filter_params(BILINEAR); |
| 224 | case USE_4_TAPS: return get_4tap_interp_filter_params(EIGHTTAP_REGULAR); |
| 225 | case USE_8_TAPS: return &av1_interp_filter_params_list[EIGHTTAP_REGULAR]; |
| 226 | default: assert(0); return NULL; |
| 227 | } |
Yunqing Wang | 91c9b2e | 2018-09-11 16:13:49 -0700 | [diff] [blame] | 228 | } |
| 229 | |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 230 | #ifdef __cplusplus |
| 231 | } // extern "C" |
| 232 | #endif |
| 233 | |
James Zern | e1cbb13 | 2018-08-22 14:10:36 -0700 | [diff] [blame] | 234 | #endif // AOM_AV1_COMMON_FILTER_H_ |