GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 20.5% 66 / 0 / 322
Functions: 22.2% 4 / 0 / 18
Branches: 15.3% 22 / 0 / 144

filters/overlay/444convert.cpp
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 // Overlay (c) 2003, 2004 by Klaus Post
36
37 #include "444convert.h"
38 #include "../../core/internal.h"
39 #include <avs/alignment.h>
40
41 #ifdef INTEL_INTRINSICS
42 #include "intel/444convert_sse.h"
43 #include "intel/444convert_avx2.h"
44 #endif
45
46 // fast in-place conversions from and to 4:4:4
47
48 /***** C fallback worker templates (used by all build configurations) *****/
49
50 template<typename pixel_t>
51 static void convert_yv12_chroma_to_yv24_c(BYTE *dstp8, const BYTE *srcp8, int dst_pitch, int src_pitch, int src_width, int src_height) {
52 pixel_t *dstp = reinterpret_cast<pixel_t *>(dstp8);
53 const pixel_t *srcp = reinterpret_cast<const pixel_t *>(srcp8);
54 dst_pitch /= sizeof(pixel_t);
55 src_pitch /= sizeof(pixel_t);
56 for (int y = 0; y < src_height; ++y) {
57 for (int x = 0; x < src_width; ++x) {
58 dstp[x*2] = srcp[x];
59 dstp[x*2+1] = srcp[x];
60 dstp[x*2+dst_pitch] = srcp[x];
61 dstp[x*2+dst_pitch+1] = srcp[x];
62 }
63 dstp += dst_pitch*2;
64 srcp += src_pitch;
65 }
66 }
67
68 template<typename pixel_t>
69 static void convert_yv16_chroma_to_yv24_c(BYTE *dstp8, const BYTE *srcp8, int dst_pitch, int src_pitch, int src_width, int src_height) {
70 pixel_t *dstp = reinterpret_cast<pixel_t *>(dstp8);
71 const pixel_t *srcp = reinterpret_cast<const pixel_t *>(srcp8);
72 dst_pitch /= sizeof(pixel_t);
73 src_pitch /= sizeof(pixel_t);
74 for (int y = 0; y < src_height; ++y) {
75 for (int x = 0; x < src_width; ++x) {
76 dstp[x*2] = srcp[x];
77 dstp[x*2+1] = srcp[x];
78 }
79 dstp += dst_pitch;
80 srcp += src_pitch;
81 }
82 }
83
84 template<typename pixel_t>
85 static void convert_yv24_chroma_to_yv12_c(BYTE *dstp8, const BYTE *srcp8, int dst_pitch, int src_pitch, int dst_width, const int dst_height) {
86 const pixel_t *srcp = reinterpret_cast<const pixel_t *>(srcp8);
87 pixel_t *dstp = reinterpret_cast<pixel_t *>(dstp8);
88 dst_pitch /= sizeof(pixel_t);
89 src_pitch /= sizeof(pixel_t);
90 for (int y = 0; y < dst_height; y++) {
91 for (int x = 0; x < dst_width; x++) {
92 if constexpr (sizeof(pixel_t) == 4)
93 dstp[x] = (srcp[x * 2] + srcp[x * 2 + 1] + srcp[x * 2 + src_pitch] + srcp[x * 2 + src_pitch + 1]) * 0.25f;
94 else
95 dstp[x] = (srcp[x * 2] + srcp[x * 2 + 1] + srcp[x * 2 + src_pitch] + srcp[x * 2 + src_pitch + 1] + 2) >> 2;
96 }
97 srcp += src_pitch * 2;
98 dstp += dst_pitch;
99 }
100 }
101
102 template<typename pixel_t>
103 static void convert_yv24_chroma_to_yv16_c(BYTE *dstp8, const BYTE *srcp8, int dst_pitch, int src_pitch, int dst_width, const int dst_height) {
104 const pixel_t *srcp = reinterpret_cast<const pixel_t *>(srcp8);
105 pixel_t *dstp = reinterpret_cast<pixel_t *>(dstp8);
106 dst_pitch /= sizeof(pixel_t);
107 src_pitch /= sizeof(pixel_t);
108 for (int y = 0; y < dst_height; y++) {
109 for (int x = 0; x < dst_width; x++) {
110 if constexpr (sizeof(pixel_t) == 4)
111 dstp[x] = (srcp[x * 2] + srcp[x * 2 + 1]) * 0.5f;
112 else
113 dstp[x] = (srcp[x * 2] + srcp[x * 2 + 1] + 1) >> 1;
114 }
115 srcp += src_pitch;
116 dstp += dst_pitch;
117 }
118 }
119
120
121 /***** YUY2 <-> YUV 4:4:4 (pure C, no SIMD variant) *****/
122
123 void Convert444FromYUY2(PVideoFrame &src, PVideoFrame &dst, int pixelsize, int bits_per_pixel, IScriptEnvironment* env) {
124 AVS_UNUSED(pixelsize);
125 AVS_UNUSED(bits_per_pixel);
126 AVS_UNUSED(env);
127
128 const BYTE* srcP = src->GetReadPtr();
129 int srcPitch = src->GetPitch();
130
131 BYTE* dstY = dst->GetWritePtr(PLANAR_Y);
132 BYTE* dstU = dst->GetWritePtr(PLANAR_U);
133 BYTE* dstV = dst->GetWritePtr(PLANAR_V);
134
135 int dstPitch = dst->GetPitch();
136
137 int w = src->GetRowSize() / 2;
138 int h = src->GetHeight();
139
140 for (int y = 0; y < h; y++) {
141 for (int x = 0; x < w; x += 2) {
142 int x2 = x << 1;
143 dstY[x] = srcP[x2];
144 dstU[x] = dstU[x+1] = srcP[x2+1];
145 dstV[x] = dstV[x+1] = srcP[x2+3];
146 dstY[x+1] = srcP[x2+2];
147 }
148 srcP += srcPitch;
149 dstY += dstPitch;
150 dstU += dstPitch;
151 dstV += dstPitch;
152 }
153 }
154
155 void Convert444ToYUY2(PVideoFrame &src, PVideoFrame &dst, int pixelsize, int bits_per_pixel, IScriptEnvironment* env) {
156 AVS_UNUSED(bits_per_pixel);
157 AVS_UNUSED(env);
158
159 const BYTE* srcY = src->GetReadPtr(PLANAR_Y);
160 const BYTE* srcU = src->GetReadPtr(PLANAR_U);
161 const BYTE* srcV = src->GetReadPtr(PLANAR_V);
162
163 int srcPitch = src->GetPitch();
164
165 BYTE* dstP = dst->GetWritePtr();
166
167 int dstPitch = dst->GetPitch();
168
169 int w = src->GetRowSize() / pixelsize;
170 int h = src->GetHeight();
171
172 for (int y = 0; y < h; y++) {
173 for (int x = 0; x < w; x += 2) {
174 int x2 = x << 1;
175 dstP[x2] = srcY[x];
176 dstP[x2+1] = (srcU[x] + srcU[x+1] + 1) >> 1;
177 dstP[x2+2] = srcY[x+1];
178 dstP[x2+3] = (srcV[x] + srcV[x+1] + 1) >> 1;
179 }
180 srcY += srcPitch;
181 srcU += srcPitch;
182 srcV += srcPitch;
183 dstP += dstPitch;
184 }
185 }
186
187
188 /***** YV12 -> YUV 4:4:4 ******/
189
190 8 void Convert444FromYV12(PVideoFrame &src, PVideoFrame &dst, int pixelsize, int bits_per_pixel, IScriptEnvironment* env)
191 {
192 AVS_UNUSED(bits_per_pixel);
193 8 env->BitBlt(dst->GetWritePtr(PLANAR_Y), dst->GetPitch(PLANAR_Y), src->GetReadPtr(PLANAR_Y), src->GetPitch(PLANAR_Y), src->GetRowSize(PLANAR_Y), src->GetHeight());
194
195 8 const BYTE* srcU = src->GetReadPtr(PLANAR_U);
196 8 const BYTE* srcV = src->GetReadPtr(PLANAR_V);
197 8 int srcUVpitch = src->GetPitch(PLANAR_U);
198 8 BYTE* dstU = dst->GetWritePtr(PLANAR_U);
199 8 BYTE* dstV = dst->GetWritePtr(PLANAR_V);
200 8 int dstUVpitch = dst->GetPitch(PLANAR_U);
201 8 int width = src->GetRowSize(PLANAR_U) / pixelsize;
202 8 int height = src->GetHeight(PLANAR_U);
203
204 #ifdef INTEL_INTRINSICS
205
5/12
✗ Branch 31 → 32 not taken.
✓ Branch 31 → 33 taken 8 times.
✗ Branch 32 → 33 not taken.
✗ Branch 32 → 40 not taken.
✓ Branch 34 → 35 taken 8 times.
✗ Branch 34 → 40 not taken.
✓ Branch 36 → 37 taken 8 times.
✗ Branch 36 → 40 not taken.
✓ Branch 38 → 39 taken 8 times.
✗ Branch 38 → 40 not taken.
✓ Branch 41 → 42 taken 8 times.
✗ Branch 41 → 47 not taken.
8 if ((pixelsize == 1 || pixelsize == 2) && (env->GetCPUFlags() & CPUF_SSE2) && IsPtrAligned(dstU, 16) && IsPtrAligned(dstV, 16))
206 {
207
1/2
✓ Branch 42 → 43 taken 8 times.
✗ Branch 42 → 45 not taken.
8 if (pixelsize == 1) {
208 8 conv_yv12_to_yv24_chroma_u8_sse2(dstU, srcU, dstUVpitch, srcUVpitch, width, height);
209 8 conv_yv12_to_yv24_chroma_u8_sse2(dstV, srcV, dstUVpitch, srcUVpitch, width, height);
210 } else {
211 conv_yv12_to_yv24_chroma_u16_sse2(dstU, srcU, dstUVpitch, srcUVpitch, width, height);
212 conv_yv12_to_yv24_chroma_u16_sse2(dstV, srcV, dstUVpitch, srcUVpitch, width, height);
213 }
214 }
215 else
216 #endif
217 {
218 if (pixelsize == 1) {
219 convert_yv12_chroma_to_yv24_c<uint8_t>(dstU, srcU, dstUVpitch, srcUVpitch, width, height);
220 convert_yv12_chroma_to_yv24_c<uint8_t>(dstV, srcV, dstUVpitch, srcUVpitch, width, height);
221 } else if (pixelsize == 2) {
222 convert_yv12_chroma_to_yv24_c<uint16_t>(dstU, srcU, dstUVpitch, srcUVpitch, width, height);
223 convert_yv12_chroma_to_yv24_c<uint16_t>(dstV, srcV, dstUVpitch, srcUVpitch, width, height);
224 } else {
225 convert_yv12_chroma_to_yv24_c<float>(dstU, srcU, dstUVpitch, srcUVpitch, width, height);
226 convert_yv12_chroma_to_yv24_c<float>(dstV, srcV, dstUVpitch, srcUVpitch, width, height);
227 }
228 }
229
230 8 env->BitBlt(dst->GetWritePtr(PLANAR_A), dst->GetPitch(PLANAR_A),
231 src->GetReadPtr(PLANAR_A), src->GetPitch(PLANAR_A), dst->GetRowSize(PLANAR_A), dst->GetHeight(PLANAR_A));
232 8 }
233
234
235 /***** YV16 -> YUV 4:4:4 ******/
236
237 4 void Convert444FromYV16(PVideoFrame &src, PVideoFrame &dst, int pixelsize, int bits_per_pixel, IScriptEnvironment* env)
238 {
239 AVS_UNUSED(bits_per_pixel);
240 4 env->BitBlt(dst->GetWritePtr(PLANAR_Y), dst->GetPitch(PLANAR_Y), src->GetReadPtr(PLANAR_Y), src->GetPitch(PLANAR_Y), src->GetRowSize(PLANAR_Y), src->GetHeight());
241
242 4 const BYTE* srcU = src->GetReadPtr(PLANAR_U);
243 4 const BYTE* srcV = src->GetReadPtr(PLANAR_V);
244 4 int srcUVpitch = src->GetPitch(PLANAR_U);
245 4 BYTE* dstU = dst->GetWritePtr(PLANAR_U);
246 4 BYTE* dstV = dst->GetWritePtr(PLANAR_V);
247 4 int dstUVpitch = dst->GetPitch(PLANAR_U);
248 4 int width = src->GetRowSize(PLANAR_U) / pixelsize;
249 4 int height = src->GetHeight(PLANAR_U);
250
251 #ifdef INTEL_INTRINSICS
252
5/12
✗ Branch 31 → 32 not taken.
✓ Branch 31 → 33 taken 4 times.
✗ Branch 32 → 33 not taken.
✗ Branch 32 → 40 not taken.
✓ Branch 34 → 35 taken 4 times.
✗ Branch 34 → 40 not taken.
✓ Branch 36 → 37 taken 4 times.
✗ Branch 36 → 40 not taken.
✓ Branch 38 → 39 taken 4 times.
✗ Branch 38 → 40 not taken.
✓ Branch 41 → 42 taken 4 times.
✗ Branch 41 → 47 not taken.
4 if ((pixelsize == 1 || pixelsize == 2) && (env->GetCPUFlags() & CPUF_SSE2) && IsPtrAligned(dstU, 16) && IsPtrAligned(dstV, 16))
253 {
254
1/2
✓ Branch 42 → 43 taken 4 times.
✗ Branch 42 → 45 not taken.
4 if (pixelsize == 1) {
255 4 conv_yv16_to_yv24_chroma_u8_sse2(dstU, srcU, dstUVpitch, srcUVpitch, width, height);
256 4 conv_yv16_to_yv24_chroma_u8_sse2(dstV, srcV, dstUVpitch, srcUVpitch, width, height);
257 } else {
258 conv_yv16_to_yv24_chroma_u16_sse2(dstU, srcU, dstUVpitch, srcUVpitch, width, height);
259 conv_yv16_to_yv24_chroma_u16_sse2(dstV, srcV, dstUVpitch, srcUVpitch, width, height);
260 }
261 }
262 else
263 #endif
264 {
265 if (pixelsize == 1) {
266 convert_yv16_chroma_to_yv24_c<uint8_t>(dstU, srcU, dstUVpitch, srcUVpitch, width, height);
267 convert_yv16_chroma_to_yv24_c<uint8_t>(dstV, srcV, dstUVpitch, srcUVpitch, width, height);
268 } else if (pixelsize == 2) {
269 convert_yv16_chroma_to_yv24_c<uint16_t>(dstU, srcU, dstUVpitch, srcUVpitch, width, height);
270 convert_yv16_chroma_to_yv24_c<uint16_t>(dstV, srcV, dstUVpitch, srcUVpitch, width, height);
271 } else {
272 convert_yv16_chroma_to_yv24_c<float>(dstU, srcU, dstUVpitch, srcUVpitch, width, height);
273 convert_yv16_chroma_to_yv24_c<float>(dstV, srcV, dstUVpitch, srcUVpitch, width, height);
274 }
275 }
276
277 4 env->BitBlt(dst->GetWritePtr(PLANAR_A), dst->GetPitch(PLANAR_A),
278 src->GetReadPtr(PLANAR_A), src->GetPitch(PLANAR_A), dst->GetRowSize(PLANAR_A), dst->GetHeight(PLANAR_A));
279 4 }
280
281 #if 0
282 // kept for historical reasons, but not used anymore (mask down conversion, now masks are done in "rowprep" functions)
283
284 /***** YV24 -> YV12 chroma downsampler (single-plane, used by imghelpers) *****/
285
286 void ConvertYToYV12Chroma(BYTE *dst, BYTE *src, int dstpitch, int srcpitch, int pixelsize, int w, int h, IScriptEnvironment* env)
287 {
288 #ifdef INTEL_INTRINSICS
289 if (env->GetCPUFlags() & CPUF_SSE2)
290 {
291 if (pixelsize == 1) {
292 if (env->GetCPUFlags() & CPUF_AVX2)
293 convert_yv24_chroma_to_yv12_u8_avx2(dst, src, dstpitch, srcpitch, w, h);
294 else if (env->GetCPUFlags() & CPUF_SSSE3)
295 convert_yv24_chroma_to_yv12_u8_ssse3(dst, src, dstpitch, srcpitch, w, h);
296 else
297 convert_yv24_chroma_to_yv12_c<uint8_t>(dst, src, dstpitch, srcpitch, w, h);
298 }
299 else if (pixelsize == 2) {
300 // No bits_per_pixel here — conservative true-16-bit path.
301 if (env->GetCPUFlags() & CPUF_AVX2)
302 convert_yv24_chroma_to_yv12_u16_avx2(dst, src, dstpitch, srcpitch, w * pixelsize, h);
303 else if (env->GetCPUFlags() & CPUF_SSE4)
304 convert_yv24_chroma_to_yv12_u16_sse41(dst, src, dstpitch, srcpitch, w * pixelsize, h);
305 else
306 conv_yv24_to_yv12_chroma_u16_true16bit_sse2(dst, src, dstpitch, srcpitch, w * pixelsize, h);
307 }
308 else
309 convert_yv24_chroma_to_yv12_float_sse2(dst, src, dstpitch, srcpitch, w * pixelsize, h);
310 return;
311 }
312 #endif
313 if (pixelsize == 1)
314 convert_yv24_chroma_to_yv12_c<uint8_t>(dst, src, dstpitch, srcpitch, w, h);
315 else if (pixelsize == 2)
316 convert_yv24_chroma_to_yv12_c<uint16_t>(dst, src, dstpitch, srcpitch, w, h);
317 else
318 convert_yv24_chroma_to_yv12_c<float>(dst, src, dstpitch, srcpitch, w, h);
319 }
320
321
322 /***** YV24 -> YV16 chroma downsampler (single-plane, used by imghelpers) *****/
323
324 void ConvertYToYV16Chroma(BYTE *dst, BYTE *src, int dstpitch, int srcpitch, int pixelsize, int w, int h, IScriptEnvironment* env)
325 {
326 #ifdef INTEL_INTRINSICS
327 if ((env->GetCPUFlags() & CPUF_SSE2) && IsPtrAligned(src, 16) && IsPtrAligned(dst, 16)
328 && w * pixelsize >= 16)
329 {
330 if (pixelsize == 1)
331 conv_yv24_to_yv16_chroma_u8_sse2(dst, src, dstpitch, srcpitch, w, h);
332 else if (pixelsize == 2) {
333 if (env->GetCPUFlags() & CPUF_SSE4)
334 conv_yv24_to_yv16_chroma_u16_sse41(dst, src, dstpitch, srcpitch, w * pixelsize, h);
335 else
336 conv_yv24_to_yv16_chroma_u16_sse2(dst, src, dstpitch, srcpitch, w * pixelsize, h);
337 }
338 else
339 convert_yv24_chroma_to_yv16_float_sse2(dst, src, dstpitch, srcpitch, w * pixelsize, h);
340 return;
341 }
342 #endif
343 if (pixelsize == 1)
344 convert_yv24_chroma_to_yv16_c<uint8_t>(dst, src, dstpitch, srcpitch, w, h);
345 else if (pixelsize == 2)
346 convert_yv24_chroma_to_yv16_c<uint16_t>(dst, src, dstpitch, srcpitch, w, h);
347 else
348 convert_yv24_chroma_to_yv16_c<float>(dst, src, dstpitch, srcpitch, w, h);
349 }
350 #endif
351
352 /***** YUV 4:4:4 -> YV16 ******/
353
354 2 void Convert444ToYV16(PVideoFrame &src, PVideoFrame &dst, int pixelsize, int bits_per_pixel, IScriptEnvironment* env)
355 {
356 AVS_UNUSED(bits_per_pixel);
357 2 env->BitBlt(dst->GetWritePtr(PLANAR_Y), dst->GetPitch(PLANAR_Y),
358 src->GetReadPtr(PLANAR_Y), src->GetPitch(), dst->GetRowSize(PLANAR_Y), dst->GetHeight());
359
360 2 const BYTE* srcU = src->GetReadPtr(PLANAR_U);
361 2 const BYTE* srcV = src->GetReadPtr(PLANAR_V);
362 2 int srcUVpitch = src->GetPitch(PLANAR_U);
363 2 BYTE* dstU = dst->GetWritePtr(PLANAR_U);
364 2 BYTE* dstV = dst->GetWritePtr(PLANAR_V);
365 2 int dstUVpitch = dst->GetPitch(PLANAR_U);
366 2 int w = dst->GetRowSize(PLANAR_U);
367 2 int h = dst->GetHeight(PLANAR_U);
368
369 #ifdef INTEL_INTRINSICS
370
6/12
✓ Branch 32 → 33 taken 2 times.
✗ Branch 32 → 42 not taken.
✓ Branch 34 → 35 taken 2 times.
✗ Branch 34 → 42 not taken.
✓ Branch 36 → 37 taken 2 times.
✗ Branch 36 → 42 not taken.
✓ Branch 38 → 39 taken 2 times.
✗ Branch 38 → 42 not taken.
✓ Branch 40 → 41 taken 2 times.
✗ Branch 40 → 42 not taken.
✓ Branch 43 → 44 taken 2 times.
✗ Branch 43 → 56 not taken.
2 if ((env->GetCPUFlags() & CPUF_SSE2) && IsPtrAligned(srcU, 16) && IsPtrAligned(srcV, 16) && IsPtrAligned(dstU, 16) && IsPtrAligned(dstV, 16))
371 {
372
1/2
✓ Branch 44 → 45 taken 2 times.
✗ Branch 44 → 47 not taken.
2 if (pixelsize == 1) {
373 2 conv_yv24_to_yv16_chroma_u8_sse2(dstU, srcU, dstUVpitch, srcUVpitch, w, h);
374 2 conv_yv24_to_yv16_chroma_u8_sse2(dstV, srcV, dstUVpitch, srcUVpitch, w, h);
375 }
376 else if (pixelsize == 2) {
377 if (env->GetCPUFlags() & CPUF_SSE4) {
378 conv_yv24_to_yv16_chroma_u16_sse41(dstU, srcU, dstUVpitch, srcUVpitch, w, h);
379 conv_yv24_to_yv16_chroma_u16_sse41(dstV, srcV, dstUVpitch, srcUVpitch, w, h);
380 } else {
381 conv_yv24_to_yv16_chroma_u16_sse2(dstU, srcU, dstUVpitch, srcUVpitch, w, h);
382 conv_yv24_to_yv16_chroma_u16_sse2(dstV, srcV, dstUVpitch, srcUVpitch, w, h);
383 }
384 }
385 else {
386 convert_yv24_chroma_to_yv16_float_sse2(dstU, srcU, dstUVpitch, srcUVpitch, w, h);
387 convert_yv24_chroma_to_yv16_float_sse2(dstV, srcV, dstUVpitch, srcUVpitch, w, h);
388 }
389 }
390 else
391 #endif
392 {
393 if (pixelsize == 1) {
394 convert_yv24_chroma_to_yv16_c<uint8_t>(dstU, srcU, dstUVpitch, srcUVpitch, w, h);
395 convert_yv24_chroma_to_yv16_c<uint8_t>(dstV, srcV, dstUVpitch, srcUVpitch, w, h);
396 } else if (pixelsize == 2) {
397 convert_yv24_chroma_to_yv16_c<uint16_t>(dstU, srcU, dstUVpitch, srcUVpitch, w, h);
398 convert_yv24_chroma_to_yv16_c<uint16_t>(dstV, srcV, dstUVpitch, srcUVpitch, w, h);
399 } else {
400 convert_yv24_chroma_to_yv16_c<float>(dstU, srcU, dstUVpitch, srcUVpitch, w, h);
401 convert_yv24_chroma_to_yv16_c<float>(dstV, srcV, dstUVpitch, srcUVpitch, w, h);
402 }
403 }
404
405 2 env->BitBlt(dst->GetWritePtr(PLANAR_A), dst->GetPitch(PLANAR_A),
406 src->GetReadPtr(PLANAR_A), src->GetPitch(PLANAR_A), dst->GetRowSize(PLANAR_A), dst->GetHeight(PLANAR_A));
407 2 }
408
409
410 /***** YUV 4:4:4 -> YV12 ******/
411
412 4 void Convert444ToYV12(PVideoFrame &src, PVideoFrame &dst, int pixelsize, int bits_per_pixel, IScriptEnvironment* env)
413 {
414 4 env->BitBlt(dst->GetWritePtr(PLANAR_Y), dst->GetPitch(PLANAR_Y),
415 src->GetReadPtr(PLANAR_Y), src->GetPitch(), dst->GetRowSize(PLANAR_Y), dst->GetHeight());
416
417 4 const BYTE* srcU = src->GetReadPtr(PLANAR_U);
418 4 const BYTE* srcV = src->GetReadPtr(PLANAR_V);
419 4 int srcUVpitch = src->GetPitch(PLANAR_U);
420 4 BYTE* dstU = dst->GetWritePtr(PLANAR_U);
421 4 BYTE* dstV = dst->GetWritePtr(PLANAR_V);
422 4 int dstUVpitch = dst->GetPitch(PLANAR_U);
423 4 int w = dst->GetRowSize(PLANAR_U); // bytes
424 4 int h = dst->GetHeight(PLANAR_U);
425
426 #ifdef INTEL_INTRINSICS
427
1/2
✓ Branch 32 → 33 taken 4 times.
✗ Branch 32 → 72 not taken.
4 if (env->GetCPUFlags() & CPUF_SSE2)
428 {
429 4 const bool has_avx2 = (env->GetCPUFlags() & CPUF_AVX2) != 0;
430
431
1/2
✓ Branch 34 → 35 taken 4 times.
✗ Branch 34 → 44 not taken.
4 if (pixelsize == 1) {
432
1/2
✓ Branch 35 → 36 taken 4 times.
✗ Branch 35 → 38 not taken.
4 if (has_avx2) {
433 4 convert_yv24_chroma_to_yv12_u8_avx2(dstU, srcU, dstUVpitch, srcUVpitch, w, h);
434 4 convert_yv24_chroma_to_yv12_u8_avx2(dstV, srcV, dstUVpitch, srcUVpitch, w, h);
435 }
436 else if (env->GetCPUFlags() & CPUF_SSSE3) {
437 convert_yv24_chroma_to_yv12_u8_ssse3(dstU, srcU, dstUVpitch, srcUVpitch, w, h);
438 convert_yv24_chroma_to_yv12_u8_ssse3(dstV, srcV, dstUVpitch, srcUVpitch, w, h);
439 }
440 else {
441 convert_yv24_chroma_to_yv12_c<uint8_t>(dstU, srcU, dstUVpitch, srcUVpitch, w, h);
442 convert_yv24_chroma_to_yv12_c<uint8_t>(dstV, srcV, dstUVpitch, srcUVpitch, w, h);
443 }
444 }
445 else if (pixelsize == 2) {
446 const bool lt16 = bits_per_pixel < 16;
447 if (has_avx2 && lt16) {
448 convert_yv24_chroma_to_yv12_u16_lessthan16bit_avx2(dstU, srcU, dstUVpitch, srcUVpitch, w, h);
449 convert_yv24_chroma_to_yv12_u16_lessthan16bit_avx2(dstV, srcV, dstUVpitch, srcUVpitch, w, h);
450 }
451 else if (has_avx2) {
452 convert_yv24_chroma_to_yv12_u16_avx2(dstU, srcU, dstUVpitch, srcUVpitch, w, h);
453 convert_yv24_chroma_to_yv12_u16_avx2(dstV, srcV, dstUVpitch, srcUVpitch, w, h);
454 }
455 else if (lt16 && (env->GetCPUFlags() & CPUF_SSSE3)) {
456 convert_yv24_chroma_to_yv12_u16_lessthan16bit_ssse3(dstU, srcU, dstUVpitch, srcUVpitch, w, h);
457 convert_yv24_chroma_to_yv12_u16_lessthan16bit_ssse3(dstV, srcV, dstUVpitch, srcUVpitch, w, h);
458 }
459 else if (env->GetCPUFlags() & CPUF_SSE4) {
460 convert_yv24_chroma_to_yv12_u16_sse41(dstU, srcU, dstUVpitch, srcUVpitch, w, h);
461 convert_yv24_chroma_to_yv12_u16_sse41(dstV, srcV, dstUVpitch, srcUVpitch, w, h);
462 }
463 else if (lt16) {
464 conv_yv24_to_yv12_chroma_u16_lessthan16bit_sse2(dstU, srcU, dstUVpitch, srcUVpitch, w, h);
465 conv_yv24_to_yv12_chroma_u16_lessthan16bit_sse2(dstV, srcV, dstUVpitch, srcUVpitch, w, h);
466 }
467 else {
468 conv_yv24_to_yv12_chroma_u16_true16bit_sse2(dstU, srcU, dstUVpitch, srcUVpitch, w, h);
469 conv_yv24_to_yv12_chroma_u16_true16bit_sse2(dstV, srcV, dstUVpitch, srcUVpitch, w, h);
470 }
471 }
472 else {
473 convert_yv24_chroma_to_yv12_float_sse2(dstU, srcU, dstUVpitch, srcUVpitch, w, h);
474 convert_yv24_chroma_to_yv12_float_sse2(dstV, srcV, dstUVpitch, srcUVpitch, w, h);
475 }
476 }
477 else
478 #endif
479 {
480 // w is GetRowSize (bytes); C template loops over pixels, so divide by pixelsize.
481 if (pixelsize == 1) {
482 convert_yv24_chroma_to_yv12_c<uint8_t>(dstU, srcU, dstUVpitch, srcUVpitch, w, h);
483 convert_yv24_chroma_to_yv12_c<uint8_t>(dstV, srcV, dstUVpitch, srcUVpitch, w, h);
484 }
485 else if (pixelsize == 2) {
486 convert_yv24_chroma_to_yv12_c<uint16_t>(dstU, srcU, dstUVpitch, srcUVpitch, w / 2, h);
487 convert_yv24_chroma_to_yv12_c<uint16_t>(dstV, srcV, dstUVpitch, srcUVpitch, w / 2, h);
488 }
489 else {
490 convert_yv24_chroma_to_yv12_c<float>(dstU, srcU, dstUVpitch, srcUVpitch, w / 4, h);
491 convert_yv24_chroma_to_yv12_c<float>(dstV, srcV, dstUVpitch, srcUVpitch, w / 4, h);
492 }
493 }
494
495 4 env->BitBlt(dst->GetWritePtr(PLANAR_A), dst->GetPitch(PLANAR_A),
496 src->GetReadPtr(PLANAR_A), src->GetPitch(PLANAR_A), dst->GetRowSize(PLANAR_A), dst->GetHeight(PLANAR_A));
497 4 }
498