GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 445 / 0 / 445
Functions: 100.0% 8 / 0 / 8
Branches: 100.0% 48 / 0 / 48

filters/overlay/intel/OF_multiply_avx2.cpp
Line Branch Exec Source
1 // Avisynth+
2 // https://avs-plus.net
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 #include "avisynth.h"
36 #include "OF_multiply_avx2.h"
37
38 #include <stdint.h>
39
40 #ifdef _MSC_VER
41 #include <intrin.h>
42 #else
43 #include <x86intrin.h>
44 #endif
45 #include <immintrin.h>
46
47 template<typename pixel_t>
48 static AVS_FORCEINLINE __m256 Eightpixels_to_floats(const pixel_t* src) {
49 __m256i srci;
50 if constexpr (sizeof(pixel_t) == 1) {
51 114 srci = _mm256_cvtepu8_epi32(_mm_loadl_epi64(reinterpret_cast<const __m128i*>(src)));
52 }
53 else {
54 180 srci = _mm256_cvtepu16_epi32(_mm_loadu_si128(reinterpret_cast<const __m128i*>(src)));
55 }
56 147 return _mm256_cvtepi32_ps(srci);
57 }
58
59 template<typename pixel_t>
60 static AVS_FORCEINLINE __m256 EightChromapixels_to_floats(const pixel_t* src, const __m256i half) {
61 __m256i srci;
62 if constexpr (sizeof(pixel_t) == 1) {
63 60 srci = _mm256_cvtepu8_epi32(_mm_loadl_epi64(reinterpret_cast<const __m128i*>(src)));
64 }
65 else {
66 108 srci = _mm256_cvtepu16_epi32(_mm_loadu_si128(reinterpret_cast<const __m128i*>(src)));
67 }
68 84 srci = _mm256_sub_epi32(srci, half);
69 84 return _mm256_cvtepi32_ps(srci);
70 }
71
72 template<typename pixel_t>
73 static AVS_FORCEINLINE void Store_Eightpixels(pixel_t* dst, __m256 what, const __m256 rounder) {
74 42 what = _mm256_add_ps(what, rounder); // round
75 42 __m256i si32 = _mm256_cvttps_epi32(what); // truncate
76 42 __m256i result = _mm256_packus_epi32(si32, si32); // only low 8 words needed
77 42 result = _mm256_permute4x64_epi64(result, (0 << 0) | (2 << 2) | (1 << 4) | (3 << 6));
78 42 __m128i result128 = _mm256_castsi256_si128(result);
79 if constexpr (sizeof(pixel_t) == 1) {
80 15 __m128i result64 = _mm_packus_epi16(result128, result128);
81 _mm_storel_epi64(reinterpret_cast<__m128i*>(dst), result64);
82 } else {
83 _mm_storeu_si128(reinterpret_cast<__m128i*>(dst), result128);
84 }
85 42 }
86
87 template<typename pixel_t>
88 static AVS_FORCEINLINE void Store_EightChromapixels(pixel_t* dst, __m256 what, const __m256 half_plus_rounder) {
89 84 what = _mm256_add_ps(what, half_plus_rounder); // chroma offset back with rounder
90 84 __m256i si32 = _mm256_cvttps_epi32(what); // truncate
91 84 __m256i result = _mm256_packus_epi32(si32, si32); // only low 8 words needed
92 84 result = _mm256_permute4x64_epi64(result, (0 << 0) | (2 << 2) | (1 << 4) | (3 << 6));
93 84 __m128i result128 = _mm256_castsi256_si128(result);
94 if constexpr (sizeof(pixel_t) == 1) {
95 30 __m128i result64 = _mm_packus_epi16(result128, result128);
96 _mm_storel_epi64(reinterpret_cast<__m128i*>(dst), result64);
97 }
98 else {
99 _mm_storeu_si128(reinterpret_cast<__m128i*>(dst), result128);
100 }
101 84 }
102
103
104 template<typename pixel_t, bool opacity_is_full, bool has_mask>
105 #if defined(GCC) || defined(CLANG)
106 __attribute__((__target__("avx2")))
107 #endif
108 14 void of_multiply_avx2(
109 int bits_per_pixel,
110 const float opacity_f,
111 const int opacity,
112 int width, int height,
113 const pixel_t* ovY,
114 int overlaypitch,
115 pixel_t* baseY, pixel_t* baseU, pixel_t* baseV,
116 int basepitch,
117 const pixel_t* maskY, const pixel_t* maskU, const pixel_t* maskV,
118 int maskpitch
119 )
120 {
121 14 const int max_pixel_value = (sizeof(pixel_t) == 1) ? 255 : (1 << bits_per_pixel) - 1;
122 14 const float factor = 1.0f / max_pixel_value;
123 14 const int half_i = sizeof(pixel_t) == 1 ? 128 : 1 << (bits_per_pixel - 1);
124 14 const float half_f = (float)half_i;
125
126 float factor_mul_opacity;
127 if constexpr (opacity_is_full)
128 6 factor_mul_opacity = factor * 1.0f;
129 else
130 8 factor_mul_opacity = factor * opacity_f;
131
132 14 auto opacity_simd = _mm256_set1_ps(opacity_f);
133 14 auto factor_simd = _mm256_set1_ps(factor);
134 14 auto factor_mul_opacity_simd = _mm256_set1_ps(factor_mul_opacity);
135 14 auto one_ps_simd = _mm256_set1_ps(1.0f);
136 14 const __m256i half_i_simd = _mm256_set1_epi32(half_i);
137 23 const __m256 half_and_rounder_simd = _mm256_set1_ps(half_f + 0.5f);
138 14 const __m256 rounder_simd = _mm256_set1_ps(0.5f);
139
140 14 const int wMod8 = width / 8 * 8;
141
142 // start processing
143
16/16
void of_multiply_avx2<unsigned char, false, false>(int, float, int, int, int, unsigned char const*, int, unsigned char*, unsigned char*, unsigned char*, int, unsigned char const*, unsigned char const*, unsigned char const*, int):
✓ Branch 126 → 17 taken 3 times.
✓ Branch 126 → 127 taken 1 time.
void of_multiply_avx2<unsigned char, false, true>(int, float, int, int, int, unsigned char const*, int, unsigned char*, unsigned char*, unsigned char*, int, unsigned char const*, unsigned char const*, unsigned char const*, int):
✓ Branch 176 → 17 taken 6 times.
✓ Branch 176 → 177 taken 2 times.
void of_multiply_avx2<unsigned char, true, false>(int, float, int, int, int, unsigned char const*, int, unsigned char*, unsigned char*, unsigned char*, int, unsigned char const*, unsigned char const*, unsigned char const*, int):
✓ Branch 126 → 17 taken 3 times.
✓ Branch 126 → 127 taken 1 time.
void of_multiply_avx2<unsigned char, true, true>(int, float, int, int, int, unsigned char const*, int, unsigned char*, unsigned char*, unsigned char*, int, unsigned char const*, unsigned char const*, unsigned char const*, int):
✓ Branch 176 → 17 taken 3 times.
✓ Branch 176 → 177 taken 1 time.
void of_multiply_avx2<unsigned short, false, false>(int, float, int, int, int, unsigned short const*, int, unsigned short*, unsigned short*, unsigned short*, int, unsigned short const*, unsigned short const*, unsigned short const*, int):
✓ Branch 104 → 17 taken 9 times.
✓ Branch 104 → 105 taken 3 times.
void of_multiply_avx2<unsigned short, false, true>(int, float, int, int, int, unsigned short const*, int, unsigned short*, unsigned short*, unsigned short*, int, unsigned short const*, unsigned short const*, unsigned short const*, int):
✓ Branch 142 → 17 taken 6 times.
✓ Branch 142 → 143 taken 2 times.
void of_multiply_avx2<unsigned short, true, false>(int, float, int, int, int, unsigned short const*, int, unsigned short*, unsigned short*, unsigned short*, int, unsigned short const*, unsigned short const*, unsigned short const*, int):
✓ Branch 104 → 17 taken 6 times.
✓ Branch 104 → 105 taken 2 times.
void of_multiply_avx2<unsigned short, true, true>(int, float, int, int, int, unsigned short const*, int, unsigned short*, unsigned short*, unsigned short*, int, unsigned short const*, unsigned short const*, unsigned short const*, int):
✓ Branch 142 → 17 taken 6 times.
✓ Branch 142 → 143 taken 2 times.
56 for (int y = 0; y < height; y++) {
144
16/16
void of_multiply_avx2<unsigned char, false, false>(int, float, int, int, int, unsigned char const*, int, unsigned char*, unsigned char*, unsigned char*, int, unsigned char const*, unsigned char const*, unsigned char const*, int):
✓ Branch 121 → 18 taken 3 times.
✓ Branch 121 → 122 taken 3 times.
void of_multiply_avx2<unsigned char, false, true>(int, float, int, int, int, unsigned char const*, int, unsigned char*, unsigned char*, unsigned char*, int, unsigned char const*, unsigned char const*, unsigned char const*, int):
✓ Branch 171 → 18 taken 6 times.
✓ Branch 171 → 172 taken 6 times.
void of_multiply_avx2<unsigned char, true, false>(int, float, int, int, int, unsigned char const*, int, unsigned char*, unsigned char*, unsigned char*, int, unsigned char const*, unsigned char const*, unsigned char const*, int):
✓ Branch 121 → 18 taken 3 times.
✓ Branch 121 → 122 taken 3 times.
void of_multiply_avx2<unsigned char, true, true>(int, float, int, int, int, unsigned char const*, int, unsigned char*, unsigned char*, unsigned char*, int, unsigned char const*, unsigned char const*, unsigned char const*, int):
✓ Branch 171 → 18 taken 3 times.
✓ Branch 171 → 172 taken 3 times.
void of_multiply_avx2<unsigned short, false, false>(int, float, int, int, int, unsigned short const*, int, unsigned short*, unsigned short*, unsigned short*, int, unsigned short const*, unsigned short const*, unsigned short const*, int):
✓ Branch 99 → 18 taken 9 times.
✓ Branch 99 → 100 taken 9 times.
void of_multiply_avx2<unsigned short, false, true>(int, float, int, int, int, unsigned short const*, int, unsigned short*, unsigned short*, unsigned short*, int, unsigned short const*, unsigned short const*, unsigned short const*, int):
✓ Branch 137 → 18 taken 6 times.
✓ Branch 137 → 138 taken 6 times.
void of_multiply_avx2<unsigned short, true, false>(int, float, int, int, int, unsigned short const*, int, unsigned short*, unsigned short*, unsigned short*, int, unsigned short const*, unsigned short const*, unsigned short const*, int):
✓ Branch 99 → 18 taken 6 times.
✓ Branch 99 → 100 taken 6 times.
void of_multiply_avx2<unsigned short, true, true>(int, float, int, int, int, unsigned short const*, int, unsigned short*, unsigned short*, unsigned short*, int, unsigned short const*, unsigned short const*, unsigned short const*, int):
✓ Branch 137 → 18 taken 6 times.
✓ Branch 137 → 138 taken 6 times.
84 for (int x = 0; x < wMod8; x += 8) {
145 __m256 Y, U, V;
146 // 8 pixels at a time. 8 or 16 bits to floats
147 84 __m256 ovY_ps = Eightpixels_to_floats<pixel_t>(ovY + x);
148
149 // generic, 8-16 bits
150 if constexpr (has_mask) {
151 __m256 final_opacity;
152 21 auto overlay_opacity_minus1 = _mm256_sub_ps(_mm256_mul_ps(ovY_ps, factor_simd), one_ps_simd); // ovY[x] * factor - 1.0f;
153
154 42 __m256 maskY_ps = Eightpixels_to_floats<pixel_t>(maskY + x);
155 21 final_opacity = _mm256_mul_ps(maskY_ps, factor_mul_opacity_simd); // maskY[x] * factor_mul_opacity;
156 21 auto Yfactor = _mm256_add_ps(one_ps_simd, _mm256_mul_ps(overlay_opacity_minus1, final_opacity)); // 1.0f + overlay_opacity_minus1 * final_opacity;
157 42 __m256 baseY_ps = Eightpixels_to_floats<pixel_t>(baseY + x);
158 21 Y = _mm256_mul_ps(baseY_ps, Yfactor); // Y = (int)(baseY[x] * Yfactor);
159
160 42 __m256 maskU_ps = Eightpixels_to_floats<pixel_t>(maskU + x);
161 21 final_opacity = _mm256_mul_ps(maskU_ps, factor_mul_opacity_simd); // maskY[x] * factor_mul_opacity;
162 21 auto Ufactor = _mm256_add_ps(one_ps_simd, _mm256_mul_ps(overlay_opacity_minus1, final_opacity)); // 1.0f + overlay_opacity_minus1 * final_opacity;
163 42 __m256 baseU_ps = EightChromapixels_to_floats<pixel_t>(baseU + x, half_i_simd);
164 21 U = _mm256_mul_ps(baseU_ps, Ufactor); // U = (int)((baseU[x] - half_i) * Ufactor) not yet: + half_i;
165
166 42 __m256 maskV_ps = Eightpixels_to_floats<pixel_t>(maskV + x);
167 21 final_opacity = _mm256_mul_ps(maskV_ps, factor_mul_opacity_simd); // maskY[x] * factor_mul_opacity;
168 21 auto Vfactor = _mm256_add_ps(one_ps_simd, _mm256_mul_ps(overlay_opacity_minus1, final_opacity)); // 1.0f + overlay_opacity_minus1 * final_opacity;
169 42 __m256 baseV_ps = EightChromapixels_to_floats<pixel_t>(baseV + x, half_i_simd);
170 21 V = _mm256_mul_ps(baseV_ps, Vfactor); // V = (int)((baseV[x] - half_i) * Vfactor) not yet: + half_i;
171
172 }
173 else {
174 42 auto overlay_opacity_minus1 = _mm256_sub_ps(_mm256_mul_ps(ovY_ps, factor_simd), one_ps_simd); // ovY[x] * factor - 1.0f;
175 21 auto common_factor = _mm256_add_ps(one_ps_simd, _mm256_mul_ps(overlay_opacity_minus1, opacity_simd)); // 1.0f + overlay_opacity_minus1 * opacity_f;
176
177 21 auto Yfactor = common_factor;
178 42 __m256 baseY_ps = Eightpixels_to_floats<pixel_t>(baseY + x);
179 21 Y = _mm256_mul_ps(baseY_ps, Yfactor); // Y = (int)(baseY[x] * Yfactor);
180
181 21 auto Ufactor = common_factor;
182 42 __m256 baseU_ps = EightChromapixels_to_floats<pixel_t>(baseU + x, half_i_simd);
183 21 U = _mm256_mul_ps(baseU_ps, Ufactor); // U = (int)((baseU[x] - half_i) * Ufactor) not yet: + half_i;
184
185 21 auto Vfactor = common_factor;
186 42 __m256 baseV_ps = EightChromapixels_to_floats<pixel_t>(baseV + x, half_i_simd);
187 21 V = _mm256_mul_ps(baseV_ps, Vfactor); // V = (int)((baseV[x] - half_i) * Vfactor) not yet: + half_i;
188
189 }
190
191 42 Store_Eightpixels<pixel_t>(baseY + x, Y, rounder_simd);
192 42 Store_EightChromapixels<pixel_t>(baseU + x, U, half_and_rounder_simd);
193 42 Store_EightChromapixels<pixel_t>(baseV + x, V, half_and_rounder_simd);
194
195 }
196
197
16/16
void of_multiply_avx2<unsigned char, false, false>(int, float, int, int, int, unsigned char const*, int, unsigned char*, unsigned char*, unsigned char*, int, unsigned char const*, unsigned char const*, unsigned char const*, int):
✓ Branch 124 → 123 taken 9 times.
✓ Branch 124 → 125 taken 3 times.
void of_multiply_avx2<unsigned char, false, true>(int, float, int, int, int, unsigned char const*, int, unsigned char*, unsigned char*, unsigned char*, int, unsigned char const*, unsigned char const*, unsigned char const*, int):
✓ Branch 174 → 173 taken 18 times.
✓ Branch 174 → 175 taken 6 times.
void of_multiply_avx2<unsigned char, true, false>(int, float, int, int, int, unsigned char const*, int, unsigned char*, unsigned char*, unsigned char*, int, unsigned char const*, unsigned char const*, unsigned char const*, int):
✓ Branch 124 → 123 taken 9 times.
✓ Branch 124 → 125 taken 3 times.
void of_multiply_avx2<unsigned char, true, true>(int, float, int, int, int, unsigned char const*, int, unsigned char*, unsigned char*, unsigned char*, int, unsigned char const*, unsigned char const*, unsigned char const*, int):
✓ Branch 174 → 173 taken 9 times.
✓ Branch 174 → 175 taken 3 times.
void of_multiply_avx2<unsigned short, false, false>(int, float, int, int, int, unsigned short const*, int, unsigned short*, unsigned short*, unsigned short*, int, unsigned short const*, unsigned short const*, unsigned short const*, int):
✓ Branch 102 → 101 taken 27 times.
✓ Branch 102 → 103 taken 9 times.
void of_multiply_avx2<unsigned short, false, true>(int, float, int, int, int, unsigned short const*, int, unsigned short*, unsigned short*, unsigned short*, int, unsigned short const*, unsigned short const*, unsigned short const*, int):
✓ Branch 140 → 139 taken 18 times.
✓ Branch 140 → 141 taken 6 times.
void of_multiply_avx2<unsigned short, true, false>(int, float, int, int, int, unsigned short const*, int, unsigned short*, unsigned short*, unsigned short*, int, unsigned short const*, unsigned short const*, unsigned short const*, int):
✓ Branch 102 → 101 taken 18 times.
✓ Branch 102 → 103 taken 6 times.
void of_multiply_avx2<unsigned short, true, true>(int, float, int, int, int, unsigned short const*, int, unsigned short*, unsigned short*, unsigned short*, int, unsigned short const*, unsigned short const*, unsigned short const*, int):
✓ Branch 140 → 139 taken 18 times.
✓ Branch 140 → 141 taken 6 times.
168 for (int x = wMod8; x < width; x++) {
198 // from of_mul_c
199 int Y, U, V;
200
201 // generic, 8-16 bits
202 // This part re-appears in SSE2 code (non mod4 end-of-line fragment)
203 // Unlike the old integer version here is proper rounding
204 126 const float overlay_opacity_minus1 = ovY[x] * factor - 1.0f;
205 if constexpr (has_mask) {
206 float final_opacity;
207
208 63 final_opacity = maskY[x] * factor_mul_opacity;
209 63 auto Yfactor = 1.0f + overlay_opacity_minus1 * final_opacity;
210 63 Y = (int)(baseY[x] * Yfactor + 0.5f);
211
212 63 final_opacity = maskU[x] * factor_mul_opacity;
213 63 auto Ufactor = 1.0f + overlay_opacity_minus1 * final_opacity;
214 63 U = (int)(((float)baseU[x] - half_f) * Ufactor + half_f + 0.5f);
215
216 63 final_opacity = maskV[x] * factor_mul_opacity;
217 63 auto Vfactor = 1.0f + overlay_opacity_minus1 * final_opacity;
218 63 V = (int)(((float)baseV[x] - half_f) * Vfactor + half_f + 0.5f);
219 }
220 else {
221 63 const float common_factor = 1.0f + overlay_opacity_minus1 * opacity_f;
222
223 63 auto Yfactor = common_factor;
224 63 Y = (int)((float)baseY[x] * Yfactor + 0.5f);
225
226 63 auto Ufactor = common_factor;
227 63 U = (int)(((float)baseU[x] - half_f) * Ufactor + half_f + 0.5f);
228
229 63 auto Vfactor = common_factor;
230 63 V = (int)(((float)baseV[x] - half_f) * Vfactor + half_f + 0.5f);
231
232 }
233
234 126 baseU[x] = (pixel_t)U;
235 126 baseV[x] = (pixel_t)V;
236 126 baseY[x] = (pixel_t)Y;
237 }
238
239 if constexpr (has_mask) {
240 21 maskY += maskpitch;
241 21 maskU += maskpitch;
242 21 maskV += maskpitch;
243 }
244
245 42 baseY += basepitch;
246 42 baseU += basepitch;
247 42 baseV += basepitch;
248
249 42 ovY += overlaypitch;
250
251 }
252 14 }
253
254 // instantiate
255 template void of_multiply_avx2<uint8_t, false, false>(int bits_per_pixel, const float opacity_f, const int opacity, int width, int height,
256 const uint8_t* ovY, int overlaypitch, uint8_t* baseY, uint8_t* baseU, uint8_t* baseV, int basepitch, const uint8_t* maskY, const uint8_t* maskU, const uint8_t* maskV, int maskpitch);
257 template void of_multiply_avx2<uint8_t, false, true>(int bits_per_pixel, const float opacity_f, const int opacity, int width, int height,
258 const uint8_t* ovY, int overlaypitch, uint8_t* baseY, uint8_t* baseU, uint8_t* baseV, int basepitch, const uint8_t* maskY, const uint8_t* maskU, const uint8_t* maskV, int maskpitch);
259 template void of_multiply_avx2<uint8_t, true, false>(int bits_per_pixel, const float opacity_f, const int opacity, int width, int height,
260 const uint8_t* ovY, int overlaypitch, uint8_t* baseY, uint8_t* baseU, uint8_t* baseV, int basepitch, const uint8_t* maskY, const uint8_t* maskU, const uint8_t* maskV, int maskpitch);
261 template void of_multiply_avx2<uint8_t, true, true>(int bits_per_pixel, const float opacity_f, const int opacity, int width, int height,
262 const uint8_t* ovY, int overlaypitch, uint8_t* baseY, uint8_t* baseU, uint8_t* baseV, int basepitch, const uint8_t* maskY, const uint8_t* maskU, const uint8_t* maskV, int maskpitch);
263 template void of_multiply_avx2<uint16_t, false, false>(int bits_per_pixel, const float opacity_f, const int opacity, int width, int height,
264 const uint16_t* ovY, int overlaypitch, uint16_t* baseY, uint16_t* baseU, uint16_t* baseV, int basepitch, const uint16_t* maskY, const uint16_t* maskU, const uint16_t* maskV, int maskpitch);
265 template void of_multiply_avx2<uint16_t, false, true>(int bits_per_pixel, const float opacity_f, const int opacity, int width, int height,
266 const uint16_t* ovY, int overlaypitch, uint16_t* baseY, uint16_t* baseU, uint16_t* baseV, int basepitch, const uint16_t* maskY, const uint16_t* maskU, const uint16_t* maskV, int maskpitch);
267 template void of_multiply_avx2<uint16_t, true, false>(int bits_per_pixel, const float opacity_f, const int opacity, int width, int height,
268 const uint16_t* ovY, int overlaypitch, uint16_t* baseY, uint16_t* baseU, uint16_t* baseV, int basepitch, const uint16_t* maskY, const uint16_t* maskU, const uint16_t* maskV, int maskpitch);
269 template void of_multiply_avx2<uint16_t, true, true>(int bits_per_pixel, const float opacity_f, const int opacity, int width, int height,
270 const uint16_t* ovY, int overlaypitch, uint16_t* baseY, uint16_t* baseU, uint16_t* baseV, int basepitch, const uint16_t* maskY, const uint16_t* maskU, const uint16_t* maskV, int maskpitch);
271
272