GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 69.0% 29 / 0 / 42
Functions: 43.8% 7 / 0 / 16
Branches: 50.0% 14 / 0 / 28

filters/resample_functions.h
Line Branch Exec Source
1 // Avisynth v2.5. Copyright 2002 Ben Rudiak-Gould et al.
2 // http://avisynth.nl
3
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
17 // http://www.gnu.org/copyleft/gpl.html .
18 //
19 // Linking Avisynth statically or dynamically with other modules is making a
20 // combined work based on Avisynth. Thus, the terms and conditions of the GNU
21 // General Public License cover the whole combination.
22 //
23 // As a special exception, the copyright holders of Avisynth give you
24 // permission to link Avisynth with independent modules that communicate with
25 // Avisynth solely through the interfaces defined in avisynth.h, regardless of the license
26 // terms of these independent modules, and to copy and distribute the
27 // resulting combined work under terms of your choice, provided that
28 // every copy of the combined work is accompanied by a complete copy of
29 // the source code of Avisynth (the version of Avisynth used to produce the
30 // combined work), being distributed under the terms of the GNU General
31 // Public License plus this exception. An independent module is a module
32 // which is not derived from or based on Avisynth, such as 3rd-party filters,
33 // import and export plugins, or graphical user interfaces.
34
35 #ifndef __Resample_Functions_H__
36 #define __Resample_Functions_H__
37
38 #include <avisynth.h>
39 #include "avs/alignment.h"
40 #include <vector>
41 #include <stdint.h>
42
43 // Original value: 65536
44 // 2 bits sacrificed because of 16 bit signed MMX multiplication
45 // NOTE: Don't change this value. It's hard-coded in SIMD code.
46 constexpr int FPScale8bits = 14; // fixed point scaler 14 bit
47 constexpr int FPScale = 1 << FPScale8bits; // fixed point scaler (1<<14)
48 // for 16 bits: one bit less
49 constexpr int FPScale16bits = 13;
50 constexpr int FPScale16 = 1 << FPScale16bits; // fixed point scaler for 10-16 bit SIMD signed operation
51 // 16: fits even avx512 32-bit float Horizontal
52 // but not AVX512 uint8 case, where we process 64 pixels at a time
53 constexpr int ALIGN_RESIZER_TARGET_SIZE = 64;
54 struct SafeLimit {
55 bool overread_possible;
56 int source_overread_offset;
57 int source_overread_beyond_targetx;
58 };
59 #define M_PI 3.14159265358979323846
60
61 struct ResamplingProgram {
62 IScriptEnvironment * Env;
63 int source_size, target_size;
64 double crop_start, crop_size;
65 int filter_size;
66 int filter_size_real; // maybe less than filter_size if dimensions are small
67 int filter_size_alignment; // for info, 1 (C, nonvector-friendly), 8 (sse or avx2) or 16 (avx2)
68 int target_size_alignment; // coeff table exists (and containt zero coeffs) even beyond target_size. Helps alternative H resizers.
69
70 // Array of Integer indicate starting point of sampling
71 std::vector<int> pixel_offset;
72
73 int bits_per_pixel;
74
75 // Array of array of coefficient for each pixel
76 // {{pixel[0]_coeff}, {pixel[1]_coeff}, ...}
77 short* pixel_coefficient;
78 #if defined(INTEL_INTRINSICS_AVX512)
79 short* pixel_coefficient_AVX512_H;
80 float* pixel_coefficient_AVX512_float_H;
81 #endif
82 float* pixel_coefficient_float;
83 // Array of real kernel size, handles edge cases! <= filter_size
84 // for SIMD, coefficients are copied over a padded aligned storage
85 std::vector<short> kernel_sizes; // temporary, used during setup only
86 // 3.7.4- can be different for each line but then they get equalized and aligned.
87
88 size_t cache_size_L2; // in bytes, for possible use in resizers
89 int max_scanlines; // recommended vertical stripe for h resamplers
90
91 // In H resizers, when using SIMD loads for speed, these is a "danger zone".
92 // If SIMD load from source pixels (src+offset) over reads beyond the allocated
93 // source buffer (image scanline width), it can cause access violation.
94 // The following SafeLimit structures indicate such cases for various SIMD sizes.
95 // and how much to adjust the source pointer to avoid access violation
96 // or stop using large SIMD loads after this limit.
97 // Depending on the pixel actual size (1, 2 or 4 bytes) and filter size,
98 // the overread size can be calculated and the appropriate SafeLimit entry is used
99 // by the actual implementation of the resizer.
100 SafeLimit safelimit_filter_size_aligned = { false, -1, -1 };
101 SafeLimit safelimit_4_pixels = { false, -1, -1 };
102 SafeLimit safelimit_8_pixels = { false, -1, -1 };
103 SafeLimit safelimit_16_pixels = { false, -1, -1 };
104 SafeLimit safelimit_32_pixels = { false, -1, -1 };
105 SafeLimit safelimit_8_pixels_each8th_target = { false, -1, -1 };
106 SafeLimit safelimit_16_pixels_each8th_target = { false, -1, -1 }; // AVX2 ks8: 16-float loads, 8 pixels/cycle
107 SafeLimit safelimit_16_pixels_each16th_target = { false, -1, -1 };
108 SafeLimit safelimit_64_pixels_each32th_target = { false, -1, -1 };
109 SafeLimit safelimit_128_pixels_each64th_target = { false, -1, -1 };
110
111 int resampler_h_detect_optimal_scanline(int src_width, int tgt_width, size_t l2_cache_size_bytes, size_t pixel_size);
112 bool resize_h_planar_gather_permutex_vstripe_check(int iSamplesInTheGroup, int permutex_index_diff_limit, int kernel_size);
113
114
115 120 ResamplingProgram(int filter_size, int source_size, int target_size, double crop_start, double crop_size, int bits_per_pixel, IScriptEnvironment* env)
116 120 : Env(env), source_size(source_size), target_size(target_size), crop_start(crop_start), crop_size(crop_size), filter_size(filter_size), filter_size_real(filter_size),
117 120 bits_per_pixel(bits_per_pixel), pixel_coefficient(0), pixel_coefficient_float(0), cache_size_L2(0), max_scanlines(0)
118 {
119
120 120 filter_size_alignment = 1;
121 // align target_size to 8 units to allow safe up to 8 pixels/cycle in H resizers. modded later.
122 120 target_size_alignment = 1;
123 #if defined(INTEL_INTRINSICS_AVX512)
124 120 pixel_coefficient_AVX512_H = nullptr;
125 120 pixel_coefficient_AVX512_float_H = nullptr;
126 #endif
127 // resize_prepare_coeff can override and realign the size of coefficient table
128
2/2
✓ Branch 4 → 5 taken 108 times.
✓ Branch 4 → 7 taken 12 times.
120 if (bits_per_pixel < 32)
129
1/2
✓ Branch 5 → 6 taken 108 times.
✗ Branch 5 → 21 not taken.
108 pixel_coefficient = (short*)Env->Allocate(sizeof(short) * target_size * filter_size, 64, AVS_NORMAL_ALLOC);
130 else
131
1/2
✓ Branch 7 → 8 taken 12 times.
✗ Branch 7 → 21 not taken.
12 pixel_coefficient_float = (float*)Env->Allocate(sizeof(float) * target_size * filter_size, 64, AVS_NORMAL_ALLOC);
132
133
1/2
✓ Branch 9 → 10 taken 120 times.
✗ Branch 9 → 21 not taken.
120 pixel_offset.resize(target_size);
134
1/2
✓ Branch 10 → 11 taken 120 times.
✗ Branch 10 → 21 not taken.
120 kernel_sizes.resize(target_size);
135
136
3/4
✓ Branch 11 → 12 taken 12 times.
✓ Branch 11 → 13 taken 108 times.
✓ Branch 12 → 13 taken 12 times.
✗ Branch 12 → 15 not taken.
120 if ((pixel_coefficient == nullptr && bits_per_pixel < 32) ||
137
3/4
✓ Branch 13 → 14 taken 108 times.
✓ Branch 13 → 18 taken 12 times.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 18 taken 108 times.
120 (pixel_coefficient_float == nullptr && bits_per_pixel == 32)) {
138 Env->Free(pixel_coefficient);
139 Env->Free(pixel_coefficient_float);
140 Env->ThrowError("ResamplingProgram: Could not reserve memory.");
141 }
142
143
1/2
✓ Branch 18 → 19 taken 120 times.
✗ Branch 18 → 21 not taken.
120 cache_size_L2 = env->GetEnvProperty(AEP_CACHESIZE_L2);
144 120 const int pixel_size_bytes = (bits_per_pixel + 7) / 8;
145
1/2
✓ Branch 19 → 20 taken 120 times.
✗ Branch 19 → 21 not taken.
120 max_scanlines = resampler_h_detect_optimal_scanline(source_size, target_size, cache_size_L2, pixel_size_bytes);
146
147 120 };
148
149 120 ~ResamplingProgram() {
150 120 Env->Free(pixel_coefficient);
151 120 Env->Free(pixel_coefficient_float);
152 #if defined(INTEL_INTRINSICS_AVX512)
153 120 Env->Free(pixel_coefficient_AVX512_H);
154 120 Env->Free(pixel_coefficient_AVX512_float_H);
155 #endif
156 120 };
157 };
158
159 typedef struct ResamplingProgram ResamplingProgram;
160
161
162 /*******************************************
163 ***************************************
164 ** Helper classes for resample.cpp **
165 ***************************************
166 *******************************************/
167
168
169 class ResamplingFunction
170 /**
171 * Pure virtual base class for resampling functions
172 */
173 {
174 public:
175 virtual double f(double x) = 0;
176 virtual double support() = 0;
177
178 virtual ResamplingProgram* GetResamplingProgram(int source_size, double crop_start, double crop_size, int target_size, int bits_per_pixel,
179 double center_pos_src, double center_pos_dst,
180 IScriptEnvironment* env);
181 93 virtual ~ResamplingFunction() = default;
182 // virtual bool CheckValidity(int source_size, double crop_size, int target_size);
183 };
184
185 class PointFilter : public ResamplingFunction
186 /**
187 * Nearest neighbour (point sampler), used in PointResize
188 **/
189 {
190 public:
191 double f(double x);
192 12 double support() { return 0; }
193 // Pre 3.7.4 : 0.0001. Comment: 0.0 crashes it.
194 // 3.7.4- this 0 is specially handled in GetResamplingProgram
195 };
196
197
198 class TriangleFilter : public ResamplingFunction
199 /**
200 * Simple triangle filter, used in BilinearResize
201 **/
202 {
203 public:
204 double f(double x);
205 50 double support() { return 1.0; }
206 };
207
208
209 class MitchellNetravaliFilter : public ResamplingFunction
210 /**
211 * Mitchell-Netraveli filter, used in BicubicResize
212 **/
213 {
214 public:
215 MitchellNetravaliFilter(double b = 1. / 3., double c = 1. / 3.);
216 double f(double x);
217 20 double support() { return 2.0; }
218
219 private:
220 double p0,p2,p3,q0,q1,q2,q3;
221 };
222
223 class LanczosFilter : public ResamplingFunction
224 /**
225 * Lanczos filter, used in LanczosResize
226 **/
227 {
228 public:
229 LanczosFilter(int _taps = 3);
230 double f(double x);
231 38 double support() { return taps; };
232
233 private:
234 double sinc(double value);
235 double taps;
236 };
237
238 class BlackmanFilter : public ResamplingFunction
239 /**
240 * Blackman filter, used in BlackmanResize
241 **/
242 {
243 public:
244 BlackmanFilter(int _taps = 4);
245 double f(double x);
246 double support() { return taps; };
247
248 private:
249 double taps, rtaps;
250 };
251
252 // Spline16
253 class Spline16Filter : public ResamplingFunction
254 /**
255 * Spline16 of Panorama Tools is a cubic-spline, with derivative set to 0 at the edges (4x4 pixels).
256 **/
257 {
258 public:
259 double f(double x);
260 double support() { return 2.0; };
261
262 private:
263 };
264
265 // Spline36
266 class Spline36Filter : public ResamplingFunction
267 /**
268 * Spline36 is like Spline16, except that it uses 6x6=36 pixels.
269 **/
270 {
271 public:
272 double f(double x);
273 double support() { return 3.0; };
274
275 private:
276 };
277
278 // Spline64
279 class Spline64Filter : public ResamplingFunction
280 /**
281 * Spline64 is like Spline36, except that it uses 8x8=64 pixels.
282 **/
283 {
284 public:
285 double f(double x);
286 double support() { return 4.0; };
287
288 private:
289 };
290
291
292 class GaussianFilter : public ResamplingFunction
293 /**
294 * GaussianFilter, from swscale.
295 **/
296 {
297 public:
298 GaussianFilter(double p = 30.0, double _b = 2.0, double _s = 4.0);
299 double f(double x);
300 double support() { return s; }; // <3.7.4 was fixed at 4.0
301
302 private:
303 double param;
304 double b; // base value since 3.7.4
305 double s; // variable support since 3.7.4
306 };
307
308 class SincFilter : public ResamplingFunction
309 /**
310 * Sinc filter, used in SincResize
311 **/
312 {
313 public:
314 SincFilter(int _taps = 4);
315 double f(double x);
316 double support() { return taps; };
317
318 private:
319 double taps;
320 };
321
322 class SinPowerFilter : public ResamplingFunction
323 // SinPow kernel, used in SinPowResize
324 {
325 public:
326 SinPowerFilter(double p = 2.5);
327 double f(double x);
328 double support() { return 2.0; }; // 2 very important, 4 cause bugs
329
330 private:
331 double param;
332 };
333
334 class SincLin2Filter : public ResamplingFunction
335 /**
336 * SincLin2 filter, used in SincLin2Resize
337 **/
338 {
339 public:
340 SincLin2Filter(int _taps = 15);
341 double f(double x);
342 double support() { return taps; };
343
344 private:
345 double sinc(double value);
346 double taps;
347 };
348
349 class UserDefined2Filter : public ResamplingFunction
350 /**
351 * User-defined by 2 samples filter, used in UDef2Resize
352 **/
353 {
354 public:
355 UserDefined2Filter(double _b, double _c, double _s);
356 double f(double x);
357 double support() { return s; }
358
359 private:
360 double sinc(double value);
361 double a, b, c;
362 double s; // 'support' as a parameter
363 };
364
365 #endif // __Reample_Functions_H__
366