GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 35.7% 161 / 0 / 451
Functions: 39.3% 11 / 0 / 28
Branches: 34.8% 126 / 0 / 362

convert/convert_rgb.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
36 #include "convert_rgb.h"
37 #ifdef INTEL_INTRINSICS
38 #include "intel/convert_rgb_sse.h"
39 #include "intel/convert_rgb_avx2.h"
40 #ifdef INTEL_INTRINSICS_AVX512
41 #include "intel/convert_rgb_avx512.h"
42 #endif
43 #endif
44 #include <avs/alignment.h>
45
46
47 /*************************************
48 ******* RGB Helper Classes ******
49 *************************************/
50
51 2 RGBtoRGBA::RGBtoRGBA(PClip src)
52
2/4
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 14 not taken.
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 12 not taken.
2 : GenericVideoFilter(src)
53 {
54
4/6
✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 15 not taken.
✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 15 not taken.
✓ Branch 8 → 9 taken 1 time.
✓ Branch 8 → 10 taken 1 time.
2 vi.pixel_type = src->GetVideoInfo().ComponentSize() == 1 ? VideoInfo::CS_BGR32 : VideoInfo::CS_BGR64;
55 2 }
56
57 static void convert_rgb24_to_rgb32_c(const BYTE *srcp, BYTE *dstp, size_t src_pitch, size_t dst_pitch, size_t width, size_t height) {
58 for (size_t y = height; y > 0; --y) {
59 for (size_t x = 0; x < width; ++x) {
60 *reinterpret_cast<int*>(dstp + x*4) = *reinterpret_cast<const int*>(srcp+x*3) | 0xFF000000;
61 }
62 srcp += src_pitch;
63 dstp += dst_pitch;
64 }
65 }
66
67 static void convert_rgb48_to_rgb64_c(const BYTE *srcp, BYTE *dstp, size_t src_pitch, size_t dst_pitch, size_t width, size_t height) {
68 for (size_t y = height; y > 0; --y) {
69 for (size_t x = 0; x < width; ++x) {
70 *reinterpret_cast<uint64_t*>(dstp + x*8) = *reinterpret_cast<const uint64_t*>(srcp+x*6) | 0xFFFF000000000000ULL;
71 }
72 srcp += src_pitch;
73 dstp += dst_pitch;
74 }
75 }
76
77 2 PVideoFrame __stdcall RGBtoRGBA::GetFrame(int n, IScriptEnvironment* env)
78 {
79
1/2
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 30 not taken.
2 PVideoFrame src = child->GetFrame(n, env);
80
1/2
✓ Branch 4 → 5 taken 2 times.
✗ Branch 4 → 28 not taken.
2 PVideoFrame dst = env->NewVideoFrameP(vi, &src);
81
1/2
✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 26 not taken.
2 const BYTE *srcp = src->GetReadPtr();
82
1/2
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 26 not taken.
2 BYTE *dstp = dst->GetWritePtr();
83
1/2
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 26 not taken.
2 const int src_pitch = src->GetPitch();
84
1/2
✓ Branch 12 → 13 taken 2 times.
✗ Branch 12 → 26 not taken.
2 const int dst_pitch = dst->GetPitch();
85
86
1/2
✓ Branch 13 → 14 taken 2 times.
✗ Branch 13 → 26 not taken.
2 int pixelsize = vi.ComponentSize();
87
88 using conv_fn_t = void(*)(const BYTE*, BYTE*, size_t, size_t, size_t, size_t);
89 conv_fn_t fn;
90
91 #ifdef INTEL_INTRINSICS
92
2/4
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 26 not taken.
✓ Branch 15 → 16 taken 2 times.
✗ Branch 15 → 19 not taken.
2 if (env->GetCPUFlags() & CPUF_SSSE3)
93
2/2
✓ Branch 16 → 17 taken 1 time.
✓ Branch 16 → 18 taken 1 time.
2 fn = (pixelsize == 1) ? convert_rgb24_to_rgb32_ssse3 : convert_rgb48_to_rgb64_ssse3;
94 else
95 #endif
96 fn = (pixelsize == 1) ? convert_rgb24_to_rgb32_c : convert_rgb48_to_rgb64_c;
97
98
1/2
✓ Branch 22 → 23 taken 2 times.
✗ Branch 22 → 26 not taken.
2 fn(srcp, dstp, src_pitch, dst_pitch, vi.width, vi.height);
99 2 return dst;
100 2 }
101
102
103
104
105 2 RGBAtoRGB::RGBAtoRGB(PClip src)
106
2/4
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 14 not taken.
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 12 not taken.
2 : GenericVideoFilter(src)
107 {
108
4/6
✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 15 not taken.
✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 15 not taken.
✓ Branch 8 → 9 taken 1 time.
✓ Branch 8 → 10 taken 1 time.
2 vi.pixel_type = src->GetVideoInfo().ComponentSize() == 1 ? VideoInfo::CS_BGR24 : VideoInfo::CS_BGR48;
109 2 }
110
111 static void convert_rgb32_to_rgb24_c(const BYTE *srcp, BYTE *dstp, size_t src_pitch, size_t dst_pitch, size_t width, size_t height) {
112 for (size_t y = height; y > 0; --y) {
113 size_t x;
114 for (x = 0; x < width-1; ++x) {
115 *reinterpret_cast<int*>(dstp+x*3) = *reinterpret_cast<const int*>(srcp+x*4);
116 }
117 //last pixel
118 dstp[x*3+0] = srcp[x*4+0];
119 dstp[x*3+1] = srcp[x*4+1];
120 dstp[x*3+2] = srcp[x*4+2];
121
122 srcp += src_pitch;
123 dstp += dst_pitch;
124 }
125 }
126
127 static void convert_rgb64_to_rgb48_c(const BYTE *srcp, BYTE *dstp, size_t src_pitch, size_t dst_pitch, size_t width, size_t height) {
128 for (size_t y = height; y > 0; --y) {
129 size_t x;
130 for (x = 0; x < width-1; ++x) { // width-1 really!
131 *reinterpret_cast<uint64_t*>(dstp+x*6) = *reinterpret_cast<const uint64_t*>(srcp+x*8);
132 }
133 //last pixel
134 reinterpret_cast<uint16_t*>(dstp)[x*3+0] = reinterpret_cast<const uint16_t*>(srcp)[x*4+0];
135 reinterpret_cast<uint16_t*>(dstp)[x*3+1] = reinterpret_cast<const uint16_t*>(srcp)[x*4+1];
136 reinterpret_cast<uint16_t*>(dstp)[x*3+2] = reinterpret_cast<const uint16_t*>(srcp)[x*4+2];
137
138 srcp += src_pitch;
139 dstp += dst_pitch;
140 }
141 }
142
143 2 PVideoFrame __stdcall RGBAtoRGB::GetFrame(int n, IScriptEnvironment* env)
144 {
145
1/2
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 37 not taken.
2 PVideoFrame src = child->GetFrame(n, env);
146
1/2
✓ Branch 4 → 5 taken 2 times.
✗ Branch 4 → 35 not taken.
2 PVideoFrame dst = env->NewVideoFrameP(vi, &src);
147
1/2
✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 33 not taken.
2 const BYTE *srcp = src->GetReadPtr();
148
1/2
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 33 not taken.
2 BYTE *dstp = dst->GetWritePtr();
149
1/2
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 33 not taken.
2 size_t src_pitch = src->GetPitch();
150
1/2
✓ Branch 12 → 13 taken 2 times.
✗ Branch 12 → 33 not taken.
2 size_t dst_pitch = dst->GetPitch();
151
152
1/2
✓ Branch 13 → 14 taken 2 times.
✗ Branch 13 → 33 not taken.
2 int pixelsize = vi.ComponentSize();
153
154 using conv_fn_t = void(*)(const BYTE*, BYTE*, size_t, size_t, size_t, size_t);
155 2 conv_fn_t fn = nullptr;
156
157 #ifdef INTEL_INTRINSICS
158
2/4
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 33 not taken.
✓ Branch 15 → 16 taken 2 times.
✗ Branch 15 → 19 not taken.
2 if (env->GetCPUFlags() & CPUF_SSSE3)
159
2/2
✓ Branch 16 → 17 taken 1 time.
✓ Branch 16 → 18 taken 1 time.
2 fn = (pixelsize == 1) ? convert_rgb32_to_rgb24_ssse3 : convert_rgb64_to_rgb48_ssse3;
160 else if ((pixelsize == 1) && (env->GetCPUFlags() & CPUF_SSE2))
161 fn = convert_rgb32_to_rgb24_sse2;
162 else
163 #endif
164 fn = (pixelsize == 1) ? convert_rgb32_to_rgb24_c : convert_rgb64_to_rgb48_c;
165
166
1/2
✓ Branch 29 → 30 taken 2 times.
✗ Branch 29 → 33 not taken.
2 fn(srcp, dstp, src_pitch, dst_pitch, vi.width, vi.height);
167
168 2 return dst;
169 2 }
170
171 3 PackedRGBtoPlanarRGB::PackedRGBtoPlanarRGB(PClip src, bool _sourceHasAlpha, bool _targetHasAlpha)
172
2/4
✓ Branch 2 → 3 taken 3 times.
✗ Branch 2 → 18 not taken.
✓ Branch 3 → 4 taken 3 times.
✗ Branch 3 → 16 not taken.
3 : GenericVideoFilter(src), sourceHasAlpha(_sourceHasAlpha), targetHasAlpha(_targetHasAlpha)
173 {
174
4/6
✓ Branch 6 → 7 taken 3 times.
✗ Branch 6 → 19 not taken.
✓ Branch 7 → 8 taken 3 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 2 times.
✓ Branch 8 → 12 taken 1 time.
6 vi.pixel_type = src->GetVideoInfo().ComponentSize() == 1 ?
175
2/2
✓ Branch 9 → 10 taken 1 time.
✓ Branch 9 → 11 taken 1 time.
2 (targetHasAlpha ? VideoInfo::CS_RGBAP : VideoInfo::CS_RGBP) :
176
1/2
✓ Branch 12 → 13 taken 1 time.
✗ Branch 12 → 14 not taken.
1 (targetHasAlpha ? VideoInfo::CS_RGBAP16 : VideoInfo::CS_RGBP16);
177 3 }
178
179 template<typename pixel_t, int src_numcomponents, bool targetHasAlpha>
180 1 static void convert_rgb_to_rgbp_c(const BYTE* srcp, BYTE* (&dstp)[4], int src_pitch, int(&dst_pitch)[4], int width, int height) {
181 1 constexpr int bits_per_pixel = sizeof(pixel_t) == 1 ? 8 : 16;
182 1 constexpr int max_pixel_value = (1 << bits_per_pixel) - 1;
183
2/16
void convert_rgb_to_rgbp_c<unsigned char, 3, false>(unsigned char const*, unsigned char* (&) [4], int, int (&) [4], int, int):
✗ Branch 7 → 3 not taken.
✗ Branch 7 → 8 not taken.
void convert_rgb_to_rgbp_c<unsigned char, 3, true>(unsigned char const*, unsigned char* (&) [4], int, int (&) [4], int, int):
✓ Branch 7 → 3 taken 3 times.
✓ Branch 7 → 8 taken 1 time.
void convert_rgb_to_rgbp_c<unsigned char, 4, false>(unsigned char const*, unsigned char* (&) [4], int, int (&) [4], int, int):
✗ Branch 7 → 3 not taken.
✗ Branch 7 → 8 not taken.
void convert_rgb_to_rgbp_c<unsigned char, 4, true>(unsigned char const*, unsigned char* (&) [4], int, int (&) [4], int, int):
✗ Branch 7 → 3 not taken.
✗ Branch 7 → 8 not taken.
void convert_rgb_to_rgbp_c<unsigned short, 3, false>(unsigned char const*, unsigned char* (&) [4], int, int (&) [4], int, int):
✗ Branch 7 → 3 not taken.
✗ Branch 7 → 8 not taken.
void convert_rgb_to_rgbp_c<unsigned short, 3, true>(unsigned char const*, unsigned char* (&) [4], int, int (&) [4], int, int):
✗ Branch 7 → 3 not taken.
✗ Branch 7 → 8 not taken.
void convert_rgb_to_rgbp_c<unsigned short, 4, false>(unsigned char const*, unsigned char* (&) [4], int, int (&) [4], int, int):
✗ Branch 7 → 3 not taken.
✗ Branch 7 → 8 not taken.
void convert_rgb_to_rgbp_c<unsigned short, 4, true>(unsigned char const*, unsigned char* (&) [4], int, int (&) [4], int, int):
✗ Branch 7 → 3 not taken.
✗ Branch 7 → 8 not taken.
4 for (int y = height; y > 0; --y) {
184 int x;
185
2/16
void convert_rgb_to_rgbp_c<unsigned char, 3, false>(unsigned char const*, unsigned char* (&) [4], int, int (&) [4], int, int):
✗ Branch 5 → 4 not taken.
✗ Branch 5 → 6 not taken.
void convert_rgb_to_rgbp_c<unsigned char, 3, true>(unsigned char const*, unsigned char* (&) [4], int, int (&) [4], int, int):
✓ Branch 5 → 4 taken 15 times.
✓ Branch 5 → 6 taken 3 times.
void convert_rgb_to_rgbp_c<unsigned char, 4, false>(unsigned char const*, unsigned char* (&) [4], int, int (&) [4], int, int):
✗ Branch 5 → 4 not taken.
✗ Branch 5 → 6 not taken.
void convert_rgb_to_rgbp_c<unsigned char, 4, true>(unsigned char const*, unsigned char* (&) [4], int, int (&) [4], int, int):
✗ Branch 5 → 4 not taken.
✗ Branch 5 → 6 not taken.
void convert_rgb_to_rgbp_c<unsigned short, 3, false>(unsigned char const*, unsigned char* (&) [4], int, int (&) [4], int, int):
✗ Branch 5 → 4 not taken.
✗ Branch 5 → 6 not taken.
void convert_rgb_to_rgbp_c<unsigned short, 3, true>(unsigned char const*, unsigned char* (&) [4], int, int (&) [4], int, int):
✗ Branch 5 → 4 not taken.
✗ Branch 5 → 6 not taken.
void convert_rgb_to_rgbp_c<unsigned short, 4, false>(unsigned char const*, unsigned char* (&) [4], int, int (&) [4], int, int):
✗ Branch 5 → 4 not taken.
✗ Branch 5 → 6 not taken.
void convert_rgb_to_rgbp_c<unsigned short, 4, true>(unsigned char const*, unsigned char* (&) [4], int, int (&) [4], int, int):
✗ Branch 5 → 4 not taken.
✗ Branch 5 → 6 not taken.
18 for (x = 0; x < width; ++x) {
186 15 pixel_t B = reinterpret_cast<const pixel_t*>(srcp)[x * src_numcomponents + 0];
187 15 pixel_t G = reinterpret_cast<const pixel_t*>(srcp)[x * src_numcomponents + 1];
188 15 pixel_t R = reinterpret_cast<const pixel_t*>(srcp)[x * src_numcomponents + 2];
189 15 pixel_t A = 0;
190 if constexpr (targetHasAlpha)
191 15 A = (src_numcomponents == 4) ? reinterpret_cast<const pixel_t*>(srcp)[x * src_numcomponents + 3] : max_pixel_value;
192 15 reinterpret_cast<pixel_t*>(dstp[0])[x] = G;
193 15 reinterpret_cast<pixel_t*>(dstp[1])[x] = B;
194 15 reinterpret_cast<pixel_t*>(dstp[2])[x] = R;
195 if constexpr (targetHasAlpha)
196 15 reinterpret_cast<pixel_t*>(dstp[3])[x] = A;
197 }
198
199 3 srcp -= src_pitch; // source packed RGB is upside down
200 3 dstp[0] += dst_pitch[0];
201 3 dstp[1] += dst_pitch[1];
202 3 dstp[2] += dst_pitch[2];
203 if constexpr (targetHasAlpha)
204 3 dstp[3] += dst_pitch[3];
205 }
206 1 }
207
208 3 PVideoFrame __stdcall PackedRGBtoPlanarRGB::GetFrame(int n, IScriptEnvironment* env)
209 {
210
1/2
✓ Branch 3 → 4 taken 3 times.
✗ Branch 3 → 120 not taken.
3 PVideoFrame src = child->GetFrame(n, env);
211
1/2
✓ Branch 4 → 5 taken 3 times.
✗ Branch 4 → 118 not taken.
3 PVideoFrame dst = env->NewVideoFrameP(vi, &src);
212
1/2
✓ Branch 6 → 7 taken 3 times.
✗ Branch 6 → 116 not taken.
3 int src_pitch = src->GetPitch();
213
1/2
✓ Branch 8 → 9 taken 3 times.
✗ Branch 8 → 116 not taken.
3 const BYTE* srcp = src->GetReadPtr();
214 BYTE* dstp[4] = {
215
2/4
✓ Branch 10 → 11 taken 3 times.
✗ Branch 10 → 116 not taken.
✓ Branch 12 → 13 taken 3 times.
✗ Branch 12 → 116 not taken.
6 dst->GetWritePtr(PLANAR_G), dst->GetWritePtr(PLANAR_B),
216
2/4
✓ Branch 14 → 15 taken 3 times.
✗ Branch 14 → 116 not taken.
✓ Branch 16 → 17 taken 3 times.
✗ Branch 16 → 116 not taken.
6 dst->GetWritePtr(PLANAR_R), dst->GetWritePtr(PLANAR_A)
217 9 };
218 int dst_pitch[4] = {
219
2/4
✓ Branch 18 → 19 taken 3 times.
✗ Branch 18 → 116 not taken.
✓ Branch 20 → 21 taken 3 times.
✗ Branch 20 → 116 not taken.
6 dst->GetPitch(PLANAR_G), dst->GetPitch(PLANAR_B),
220
2/4
✓ Branch 22 → 23 taken 3 times.
✗ Branch 22 → 116 not taken.
✓ Branch 24 → 25 taken 3 times.
✗ Branch 24 → 116 not taken.
6 dst->GetPitch(PLANAR_R), dst->GetPitch(PLANAR_A)
221 9 };
222
1/2
✓ Branch 25 → 26 taken 3 times.
✗ Branch 25 → 116 not taken.
3 int pixelsize = vi.ComponentSize();
223 3 srcp += src_pitch * (vi.height - 1); // start from bottom: packed RGB is upside down
224
225 using conv_fn_t = void(*)(const BYTE*, BYTE* (&)[4], int, int(&)[4], int, int);
226 3 conv_fn_t fn = nullptr;
227
228
1/2
✓ Branch 26 → 27 taken 3 times.
✗ Branch 26 → 116 not taken.
3 const bool targetHasAlpha = vi.IsPlanarRGBA();
229
230 #ifdef INTEL_INTRINSICS
231
1/2
✓ Branch 27 → 28 taken 3 times.
✗ Branch 27 → 116 not taken.
3 auto CPU = env->GetCPUFlagsEx();
232 3 const bool hasSSE2 = (CPU & CPUF_SSE2) != 0;
233 3 const bool hasSSSE3 = (CPU & CPUF_SSSE3) != 0;
234 3 const bool hasAVX2 = (CPU & CPUF_AVX2) != 0;
235 #ifdef INTEL_INTRINSICS_AVX512
236 //const bool has_AVX512_base = (CPU & CPUF_AVX512_BASE) == CPUF_AVX512_BASE; // group flag!
237 3 const bool has_AVX512_fast = (CPU & CPUF_AVX512_FAST) == CPUF_AVX512_FAST; // group flag!
238 #endif
239 #endif
240
241 // for RGBA there is no width limit, we do full scanlines, Avisynth's 64 byte alignment allows
242 // processing 16 RGB32 pixels or 8 RGB64 pixels at a time
243 // RGB is tricky, remainder handling is needed.
244
245
2/2
✓ Branch 28 → 29 taken 2 times.
✓ Branch 28 → 71 taken 1 time.
3 if (pixelsize == 1) {
246
2/2
✓ Branch 29 → 30 taken 1 time.
✓ Branch 29 → 49 taken 1 time.
2 if (sourceHasAlpha) {
247 // RGB32->
248 #ifdef INTEL_INTRINSICS
249 #ifdef INTEL_INTRINSICS_AVX512
250
1/4
✗ Branch 30 → 31 not taken.
✓ Branch 30 → 34 taken 1 time.
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 33 not taken.
1 if (has_AVX512_fast) fn = targetHasAlpha ? convert_rgba_to_rgbp_avx512vbmi<uint8_t, true> : convert_rgba_to_rgbp_avx512vbmi<uint8_t, false>;
251 else
252 #endif
253
2/4
✓ Branch 34 → 35 taken 1 time.
✗ Branch 34 → 38 not taken.
✗ Branch 35 → 36 not taken.
✓ Branch 35 → 37 taken 1 time.
1 if (hasAVX2) fn = targetHasAlpha ? convert_rgba_to_rgbp_avx2<uint8_t, true> : convert_rgba_to_rgbp_avx2<uint8_t, false>;
254 else if (hasSSSE3) fn = targetHasAlpha ? convert_rgba_to_rgbp_ssse3<uint8_t, true> : convert_rgba_to_rgbp_ssse3<uint8_t, false>;
255 else if (hasSSE2) fn = targetHasAlpha ? convert_rgba_to_rgbp_sse2 <uint8_t, true> : convert_rgba_to_rgbp_sse2 <uint8_t, false>;
256 else
257 #endif
258 fn = targetHasAlpha ? convert_rgb_to_rgbp_c<uint8_t, 4, true> : convert_rgb_to_rgbp_c<uint8_t, 4, false>;
259 }
260 else {
261 // RGB24->
262 #ifdef INTEL_INTRINSICS
263 // RGB24->RGB(A)P8, works with 48byte blocks (16xRGB), min width is 16 (SSSE3, 32 (AVX2), width constraint is due to remainder handling, not alignment)
264
2/6
✓ Branch 49 → 50 taken 1 time.
✗ Branch 49 → 55 not taken.
✗ Branch 50 → 51 not taken.
✓ Branch 50 → 55 taken 1 time.
✗ Branch 51 → 52 not taken.
✗ Branch 51 → 53 not taken.
1 if (hasAVX2 && vi.width >= 32) fn = targetHasAlpha ? convert_rgb_to_rgbp_avx2 <uint8_t, true> : convert_rgb_to_rgbp_avx2 <uint8_t, false>;
265
2/6
✓ Branch 55 → 56 taken 1 time.
✗ Branch 55 → 61 not taken.
✗ Branch 56 → 57 not taken.
✓ Branch 56 → 61 taken 1 time.
✗ Branch 57 → 58 not taken.
✗ Branch 57 → 59 not taken.
1 else if (hasSSSE3 && vi.width >= 16) fn = targetHasAlpha ? convert_rgb_to_rgbp_ssse3<uint8_t, true> : convert_rgb_to_rgbp_ssse3<uint8_t, false>;
266
2/6
✓ Branch 61 → 62 taken 1 time.
✗ Branch 61 → 67 not taken.
✗ Branch 62 → 63 not taken.
✓ Branch 62 → 67 taken 1 time.
✗ Branch 63 → 64 not taken.
✗ Branch 63 → 65 not taken.
1 else if (hasSSE2 && vi.width >= 16) fn = targetHasAlpha ? convert_rgb_to_rgbp_sse2 <uint8_t, true> : convert_rgb_to_rgbp_sse2 <uint8_t, false>;
267 else
268 #endif
269
1/2
✓ Branch 67 → 68 taken 1 time.
✗ Branch 67 → 69 not taken.
1 fn = targetHasAlpha ? convert_rgb_to_rgbp_c<uint8_t, 3, true> : convert_rgb_to_rgbp_c<uint8_t, 3, false>;
270 }
271 }
272 else { // pixelsize == 2
273
1/2
✓ Branch 71 → 72 taken 1 time.
✗ Branch 71 → 91 not taken.
1 if (sourceHasAlpha) {
274 // RGB64->
275 #ifdef INTEL_INTRINSICS
276 #ifdef INTEL_INTRINSICS_AVX512
277
1/4
✗ Branch 72 → 73 not taken.
✓ Branch 72 → 76 taken 1 time.
✗ Branch 73 → 74 not taken.
✗ Branch 73 → 75 not taken.
1 if (has_AVX512_fast) fn = targetHasAlpha ? convert_rgba_to_rgbp_avx512vbmi<uint16_t, true> : convert_rgba_to_rgbp_avx512vbmi<uint16_t, false>;
278 else
279 #endif
280
2/4
✓ Branch 76 → 77 taken 1 time.
✗ Branch 76 → 80 not taken.
✓ Branch 77 → 78 taken 1 time.
✗ Branch 77 → 79 not taken.
1 if (hasAVX2) fn = targetHasAlpha ? convert_rgba_to_rgbp_avx2<uint16_t, true> : convert_rgba_to_rgbp_avx2<uint16_t, false>;
281 else if (hasSSSE3) fn = targetHasAlpha ? convert_rgba_to_rgbp_ssse3<uint16_t, true> : convert_rgba_to_rgbp_ssse3<uint16_t, false>;
282 else if (hasSSE2) fn = targetHasAlpha ? convert_rgba_to_rgbp_sse2 <uint16_t, true> : convert_rgba_to_rgbp_sse2 <uint16_t, false>;
283 else
284 #endif
285 fn = targetHasAlpha ? convert_rgb_to_rgbp_c<uint16_t, 4, true> : convert_rgb_to_rgbp_c<uint16_t, 4, false>;
286 }
287 else {
288 // RGB48->
289 // width constraint is due to remainder handling, not alignment, AVX2 needs 16 pixels (48 bytes) to process, SSE2/SSSE3 need 8 pixels (48 bytes) to process
290 #ifdef INTEL_INTRINSICS
291 if (hasAVX2 && vi.width >= 16) fn = targetHasAlpha ? convert_rgb_to_rgbp_avx2 <uint16_t, true> : convert_rgb_to_rgbp_avx2 <uint16_t, false>;
292 else if (hasSSSE3 && vi.width >= 8) fn = targetHasAlpha ? convert_rgb_to_rgbp_ssse3<uint16_t, true> : convert_rgb_to_rgbp_ssse3<uint16_t, false>;
293 else if (hasSSE2 && vi.width >= 8) fn = targetHasAlpha ? convert_rgb_to_rgbp_sse2 <uint16_t, true> : convert_rgb_to_rgbp_sse2 <uint16_t, false>;
294 else
295 #endif
296 fn = targetHasAlpha ? convert_rgb_to_rgbp_c<uint16_t, 3, true> : convert_rgb_to_rgbp_c<uint16_t, 3, false>;
297 }
298 }
299
300
1/2
✓ Branch 112 → 113 taken 3 times.
✗ Branch 112 → 116 not taken.
3 fn(srcp, dstp, src_pitch, dst_pitch, vi.width, vi.height);
301 3 return dst;
302 3 }
303
304 3 PlanarRGBtoPackedRGB::PlanarRGBtoPackedRGB(PClip src, bool _targetHasAlpha)
305
2/4
✓ Branch 2 → 3 taken 3 times.
✗ Branch 2 → 18 not taken.
✓ Branch 3 → 4 taken 3 times.
✗ Branch 3 → 16 not taken.
3 : GenericVideoFilter(src), targetHasAlpha(_targetHasAlpha)
306 {
307
4/6
✓ Branch 6 → 7 taken 3 times.
✗ Branch 6 → 19 not taken.
✓ Branch 7 → 8 taken 3 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 2 times.
✓ Branch 8 → 12 taken 1 time.
6 vi.pixel_type = src->GetVideoInfo().ComponentSize() == 1 ?
308
2/2
✓ Branch 9 → 10 taken 1 time.
✓ Branch 9 → 11 taken 1 time.
2 (targetHasAlpha ? VideoInfo::CS_BGR32 : VideoInfo::CS_BGR24) : // PlanarRGB(A)->RGB24/32
309
1/2
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 1 time.
1 (targetHasAlpha ? VideoInfo::CS_BGR64 : VideoInfo::CS_BGR48); // PlanarRGB(A)->RGB48/64
310 3 }
311
312 template<typename pixel_t, int target_numcomponents, bool hasSrcAlpha>
313 2 static void convert_rgbp_to_rgb_c(const BYTE *(&srcp)[4], BYTE * dstp, int (&src_pitch)[4], int dst_pitch, int width, int height) {
314
315 2 constexpr int bits_per_pixel = sizeof(pixel_t) == 1 ? 8 : 16;
316 2 constexpr int max_pixel_value = (1 << bits_per_pixel) - 1;
317
318
4/16
void convert_rgbp_to_rgb_c<unsigned char, 3, false>(unsigned char const* (&) [4], unsigned char*, int (&) [4], int, int, int):
✗ Branch 7 → 3 not taken.
✗ Branch 7 → 8 not taken.
void convert_rgbp_to_rgb_c<unsigned char, 3, true>(unsigned char const* (&) [4], unsigned char*, int (&) [4], int, int, int):
✓ Branch 7 → 3 taken 3 times.
✓ Branch 7 → 8 taken 1 time.
void convert_rgbp_to_rgb_c<unsigned char, 4, false>(unsigned char const* (&) [4], unsigned char*, int (&) [4], int, int, int):
✗ Branch 7 → 3 not taken.
✗ Branch 7 → 8 not taken.
void convert_rgbp_to_rgb_c<unsigned char, 4, true>(unsigned char const* (&) [4], unsigned char*, int (&) [4], int, int, int):
✗ Branch 7 → 3 not taken.
✗ Branch 7 → 8 not taken.
void convert_rgbp_to_rgb_c<unsigned short, 3, false>(unsigned char const* (&) [4], unsigned char*, int (&) [4], int, int, int):
✗ Branch 7 → 3 not taken.
✗ Branch 7 → 8 not taken.
void convert_rgbp_to_rgb_c<unsigned short, 3, true>(unsigned char const* (&) [4], unsigned char*, int (&) [4], int, int, int):
✓ Branch 7 → 3 taken 3 times.
✓ Branch 7 → 8 taken 1 time.
void convert_rgbp_to_rgb_c<unsigned short, 4, false>(unsigned char const* (&) [4], unsigned char*, int (&) [4], int, int, int):
✗ Branch 7 → 3 not taken.
✗ Branch 7 → 8 not taken.
void convert_rgbp_to_rgb_c<unsigned short, 4, true>(unsigned char const* (&) [4], unsigned char*, int (&) [4], int, int, int):
✗ Branch 7 → 3 not taken.
✗ Branch 7 → 8 not taken.
8 for (int y = 0; y < height; y++) {
319 int x;
320
4/16
void convert_rgbp_to_rgb_c<unsigned char, 3, false>(unsigned char const* (&) [4], unsigned char*, int (&) [4], int, int, int):
✗ Branch 5 → 4 not taken.
✗ Branch 5 → 6 not taken.
void convert_rgbp_to_rgb_c<unsigned char, 3, true>(unsigned char const* (&) [4], unsigned char*, int (&) [4], int, int, int):
✓ Branch 5 → 4 taken 15 times.
✓ Branch 5 → 6 taken 3 times.
void convert_rgbp_to_rgb_c<unsigned char, 4, false>(unsigned char const* (&) [4], unsigned char*, int (&) [4], int, int, int):
✗ Branch 5 → 4 not taken.
✗ Branch 5 → 6 not taken.
void convert_rgbp_to_rgb_c<unsigned char, 4, true>(unsigned char const* (&) [4], unsigned char*, int (&) [4], int, int, int):
✗ Branch 5 → 4 not taken.
✗ Branch 5 → 6 not taken.
void convert_rgbp_to_rgb_c<unsigned short, 3, false>(unsigned char const* (&) [4], unsigned char*, int (&) [4], int, int, int):
✗ Branch 5 → 4 not taken.
✗ Branch 5 → 6 not taken.
void convert_rgbp_to_rgb_c<unsigned short, 3, true>(unsigned char const* (&) [4], unsigned char*, int (&) [4], int, int, int):
✓ Branch 5 → 4 taken 15 times.
✓ Branch 5 → 6 taken 3 times.
void convert_rgbp_to_rgb_c<unsigned short, 4, false>(unsigned char const* (&) [4], unsigned char*, int (&) [4], int, int, int):
✗ Branch 5 → 4 not taken.
✗ Branch 5 → 6 not taken.
void convert_rgbp_to_rgb_c<unsigned short, 4, true>(unsigned char const* (&) [4], unsigned char*, int (&) [4], int, int, int):
✗ Branch 5 → 4 not taken.
✗ Branch 5 → 6 not taken.
36 for (x = 0; x < width; ++x) {
321 30 const pixel_t G = reinterpret_cast<const pixel_t *>(srcp[0])[x];
322 30 const pixel_t B = reinterpret_cast<const pixel_t *>(srcp[1])[x];
323 30 const pixel_t R = reinterpret_cast<const pixel_t *>(srcp[2])[x];
324 30 reinterpret_cast<pixel_t *>(dstp)[x*target_numcomponents+0] = B;
325 30 reinterpret_cast<pixel_t *>(dstp)[x*target_numcomponents+1] = G;
326 30 reinterpret_cast<pixel_t *>(dstp)[x*target_numcomponents+2] = R;
327 if constexpr (target_numcomponents == 4) { // either from A channel or default transparent constant
328 pixel_t A;
329 if constexpr (hasSrcAlpha)
330 A = reinterpret_cast<const pixel_t*>(srcp[3])[x];
331 else
332 A = max_pixel_value; // 255/65535
333 reinterpret_cast<pixel_t *>(dstp)[x*target_numcomponents + 3] = A;
334 }
335 }
336
337 6 dstp -= dst_pitch; // source packed RGB is upside down
338 6 srcp[0] += src_pitch[0];
339 6 srcp[1] += src_pitch[1];
340 6 srcp[2] += src_pitch[2];
341 if constexpr (hasSrcAlpha)
342 6 srcp[3] += src_pitch[3];
343 }
344 2 }
345
346 3 PVideoFrame __stdcall PlanarRGBtoPackedRGB::GetFrame(int n, IScriptEnvironment* env)
347 {
348
1/2
✓ Branch 3 → 4 taken 3 times.
✗ Branch 3 → 68 not taken.
3 PVideoFrame src = child->GetFrame(n, env);
349
1/2
✓ Branch 4 → 5 taken 3 times.
✗ Branch 4 → 66 not taken.
3 PVideoFrame dst = env->NewVideoFrameP(vi, &src);
350
1/2
✓ Branch 6 → 7 taken 3 times.
✗ Branch 6 → 64 not taken.
3 int dst_pitch = dst->GetPitch();
351
1/2
✓ Branch 8 → 9 taken 3 times.
✗ Branch 8 → 64 not taken.
3 BYTE* dstp = dst->GetWritePtr();
352
2/4
✓ Branch 10 → 11 taken 3 times.
✗ Branch 10 → 64 not taken.
✓ Branch 12 → 13 taken 3 times.
✗ Branch 12 → 64 not taken.
6 const BYTE* srcp[4] = { src->GetReadPtr(PLANAR_G), src->GetReadPtr(PLANAR_B),
353
2/4
✓ Branch 14 → 15 taken 3 times.
✗ Branch 14 → 64 not taken.
✓ Branch 16 → 17 taken 3 times.
✗ Branch 16 → 64 not taken.
6 src->GetReadPtr(PLANAR_R), src->GetReadPtr(PLANAR_A) };
354
2/4
✓ Branch 18 → 19 taken 3 times.
✗ Branch 18 → 64 not taken.
✓ Branch 20 → 21 taken 3 times.
✗ Branch 20 → 64 not taken.
6 int src_pitch[4] = { src->GetPitch(PLANAR_G), src->GetPitch(PLANAR_B),
355
2/4
✓ Branch 22 → 23 taken 3 times.
✗ Branch 22 → 64 not taken.
✓ Branch 24 → 25 taken 3 times.
✗ Branch 24 → 64 not taken.
6 src->GetPitch(PLANAR_R), src->GetPitch(PLANAR_A) };
356
1/2
✓ Branch 25 → 26 taken 3 times.
✗ Branch 25 → 64 not taken.
3 int pixelsize = vi.ComponentSize();
357 3 dstp += dst_pitch * (vi.height - 1); // start from bottom: packed RGB is upside down
358
359 3 const bool hasSrcAlpha = (src_pitch[3] != 0); // planar RGB_A_ source
360
1/2
✓ Branch 26 → 27 taken 3 times.
✗ Branch 26 → 64 not taken.
3 const bool hasTargetAlpha = (vi.NumComponents() == 4); // RGB32 or RGB64 target
361
362 using conv_fn_t = void(*)(const BYTE* (&)[4], BYTE*, int(&)[4], int, int, int);
363 3 conv_fn_t fn = nullptr;
364
365 #ifdef INTEL_INTRINSICS
366
1/2
✓ Branch 27 → 28 taken 3 times.
✗ Branch 27 → 64 not taken.
3 const bool hasAVX2 = (env->GetCPUFlags() & CPUF_AVX2) != 0;
367
1/2
✓ Branch 28 → 29 taken 3 times.
✗ Branch 28 → 64 not taken.
3 const bool hasSSE2 = (env->GetCPUFlags() & CPUF_SSE2) != 0;
368 #endif
369
370
2/2
✓ Branch 29 → 30 taken 2 times.
✓ Branch 29 → 45 taken 1 time.
3 if (pixelsize == 1) {
371
2/2
✓ Branch 30 → 31 taken 1 time.
✓ Branch 30 → 34 taken 1 time.
2 if (!hasTargetAlpha) { // RGB24 — no SIMD path exists
372
1/2
✓ Branch 31 → 32 taken 1 time.
✗ Branch 31 → 33 not taken.
1 fn = hasSrcAlpha ? convert_rgbp_to_rgb_c<uint8_t, 3, true> : convert_rgbp_to_rgb_c<uint8_t, 3, false>;
373 }
374 else { // RGBA32
375 #ifdef INTEL_INTRINSICS
376
1/2
✓ Branch 34 → 35 taken 1 time.
✗ Branch 34 → 38 not taken.
1 if (hasAVX2)
377
1/2
✗ Branch 35 → 36 not taken.
✓ Branch 35 → 37 taken 1 time.
1 fn = hasSrcAlpha ? convert_rgbp_to_rgba_avx2<uint8_t, true> : convert_rgbp_to_rgba_avx2<uint8_t, false>;
378 else if (hasSSE2)
379 fn = hasSrcAlpha ? convert_rgbp_to_rgba_sse2<uint8_t, true> : convert_rgbp_to_rgba_sse2<uint8_t, false>;
380 else
381 #endif
382 fn = hasSrcAlpha ? convert_rgbp_to_rgb_c<uint8_t, 4, true> : convert_rgbp_to_rgb_c<uint8_t, 4, false>;
383 }
384 }
385 else { // pixelsize == 2
386
1/2
✓ Branch 45 → 46 taken 1 time.
✗ Branch 45 → 49 not taken.
1 if (!hasTargetAlpha) { // RGB48 — no SIMD path exists
387
1/2
✓ Branch 46 → 47 taken 1 time.
✗ Branch 46 → 48 not taken.
1 fn = hasSrcAlpha ? convert_rgbp_to_rgb_c<uint16_t, 3, true> : convert_rgbp_to_rgb_c<uint16_t, 3, false>;
388 }
389 else { // RGBA64
390 #ifdef INTEL_INTRINSICS
391 if (hasAVX2)
392 fn = hasSrcAlpha ? convert_rgbp_to_rgba_avx2<uint16_t, true> : convert_rgbp_to_rgba_avx2<uint16_t, false>;
393 else if (hasSSE2)
394 fn = hasSrcAlpha ? convert_rgbp_to_rgba_sse2<uint16_t, true> : convert_rgbp_to_rgba_sse2<uint16_t, false>;
395 else
396 #endif
397 fn = hasSrcAlpha ? convert_rgbp_to_rgb_c<uint16_t, 4, true> : convert_rgbp_to_rgb_c<uint16_t, 4, false>;
398 }
399 }
400
401
1/2
✓ Branch 60 → 61 taken 3 times.
✗ Branch 60 → 64 not taken.
3 fn(srcp, dstp, src_pitch, dst_pitch, vi.width, vi.height);
402 3 return dst;
403 3 }
404