GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 77.1% 555 / 0 / 720
Functions: 76.3% 29 / 0 / 38
Branches: 56.8% 142 / 0 / 250

core/AviHelper.cpp
Line Branch Exec Source
1 // Avisynth v2.5. Copyright 2007 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 <avisynth.h>
37 #include "internal.h"
38 #ifdef INTEL_INTRINSICS
39 // Intrinsics base header + really required extension headers
40 #if defined(_MSC_VER)
41 #include <intrin.h> // MSVC
42 #else
43 #include <x86intrin.h> // GCC/MinGW/Clang/LLVM
44 #endif
45 #include <smmintrin.h> // SSE4.1
46 #endif
47
48 int AviHelper_ImageSize(const VideoInfo *vi, bool AVIPadScanlines, bool v210, bool v410, bool r210, bool R10k, bool v308, bool v408, bool Y410) {
49 int image_size;
50 if (vi->pixel_type == VideoInfo::CS_YUV444P16 || vi->pixel_type == VideoInfo::CS_YUVA444P16)
51 { // Y416 packed 4444 U,Y,V,A
52 image_size = vi->width * vi->height * 4 * sizeof(uint16_t);
53 }
54 else if (vi->pixel_type == VideoInfo::CS_RGBP10 && r210)
55 { // 3x10bit packed RGB, 64 aligned
56 image_size = ((vi->width + 63) / 64) * 256 * vi->height; // 4 byte/pixel: 32bits for 3x10 bits
57 }
58 else if (vi->pixel_type == VideoInfo::CS_RGBP10 && R10k)
59 { // 3x10bit packed RGB, no aligment
60 image_size = vi->width * 4 * vi->height; // 4 byte/pixel: 32bits for 3x10 bits
61 }
62 else if (vi->pixel_type == VideoInfo::CS_YV24 && v308)
63 { // v308 packed 444
64 image_size = vi->width * vi->height * 3 * sizeof(uint8_t);
65 }
66 else if (vi->pixel_type == VideoInfo::CS_YUVA444 && v408)
67 { // v408 packed 4444
68 image_size = vi->width * vi->height * 4 * sizeof(uint8_t);
69 }
70 else if (vi->pixel_type == VideoInfo::CS_YUV444P10 && v410)
71 { // v410 packed 444 U,Y,V
72 image_size = vi->width * vi->height * 4; // 4 byte/pixel: 32bits for 3x10 bits
73 }
74 else if ((vi->pixel_type == VideoInfo::CS_YUV444P10 || vi->pixel_type == VideoInfo::CS_YUVA444P10) && Y410)
75 { // Y410 packed 10 bit 444 U,Y,V,A (Alpha is 2 bits)
76 image_size = vi->width * vi->height * 4; // 4 byte/pixel: 32bits for 3x10+2 bits
77 }
78 else if (vi->pixel_type == VideoInfo::CS_YUV422P10 && v210)
79 {
80 image_size = ((16 * ((vi->width + 5) / 6) + 127) & ~127);
81 image_size *= vi->height;
82 }
83 else if ((vi->IsRGB() && !vi->IsPlanar()) || vi->IsYUY2() || vi->IsY() || AVIPadScanlines) {
84 // incl. all packed RGBs
85 image_size = vi->BMPSize();
86 }
87 else { // Packed size
88 if (vi->IsPlanar() && vi->IsRGB()) {
89 image_size = (vi->RowSize(PLANAR_G) * vi->height);
90 if (vi->IsPlanarRGBA()) // not supported yet, but for the sake of completeness
91 image_size *= 4;
92 else
93 image_size *= 3;
94 }
95 else {
96 image_size = vi->RowSize(PLANAR_U);
97 if (image_size) {
98 image_size *= vi->height;
99 image_size >>= vi->GetPlaneHeightSubsampling(PLANAR_U);
100 image_size *= 2;
101 }
102 image_size += vi->RowSize(PLANAR_Y) * vi->height;
103 }
104 }
105 return image_size;
106 }
107
108 #ifdef INTEL_INTRINSICS
109 template<bool hasAlpha>
110 2 void ToY416_sse2(uint8_t *outbuf, int out_pitch, const uint8_t *yptr, int ypitch, const uint8_t *uptr, const uint8_t *vptr, int uvpitch, const uint8_t *aptr, int apitch, int width, int height)
111 {
112 // out_pitch may not be mod16
113 2 const int wmod4 = (width / 4) * 4;
114
115 // UYVA
116
4/4
void ToY416_sse2<false>(unsigned char*, int, unsigned char const*, int, unsigned char const*, unsigned char const*, int, unsigned char const*, int, int, int):
✓ Branch 43 → 3 taken 3 times.
✓ Branch 43 → 44 taken 1 time.
void ToY416_sse2<true>(unsigned char*, int, unsigned char const*, int, unsigned char const*, unsigned char const*, int, unsigned char const*, int, int, int):
✓ Branch 46 → 3 taken 3 times.
✓ Branch 46 → 47 taken 1 time.
8 for (int y = 0; y < height; y++) {
117
4/4
void ToY416_sse2<false>(unsigned char*, int, unsigned char const*, int, unsigned char const*, unsigned char const*, int, unsigned char const*, int, int, int):
✓ Branch 38 → 4 taken 3 times.
✓ Branch 38 → 39 taken 3 times.
void ToY416_sse2<true>(unsigned char*, int, unsigned char const*, int, unsigned char const*, unsigned char const*, int, unsigned char const*, int, int, int):
✓ Branch 41 → 4 taken 3 times.
✓ Branch 41 → 42 taken 3 times.
12 for (int x = 0; x < wmod4; x += 4) {
118 // read 4x4 pixels, store 2x(4x2) pixels
119 6 auto u = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(uptr + x * sizeof(uint16_t)));
120 6 auto y = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(yptr + x * sizeof(uint16_t)));
121 12 auto v = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(vptr + x * sizeof(uint16_t)));
122 __m128i a;
123 if (hasAlpha)
124 6 a = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(aptr + x * sizeof(uint16_t)));
125 else
126 3 a = _mm_set1_epi16(-1); // transparent alpha 0xFFFF
127 6 auto uy = _mm_unpacklo_epi16(u, y);
128 6 auto va = _mm_unpacklo_epi16(v, a);
129 6 auto uyva_lo = _mm_unpacklo_epi32(uy, va);
130 6 _mm_storeu_si128(reinterpret_cast<__m128i *>(outbuf + 4 * sizeof(uint16_t) * x), uyva_lo);
131 6 auto uyva_hi = _mm_unpackhi_epi32(uy, va);
132 6 _mm_storeu_si128(reinterpret_cast<__m128i *>(outbuf + 16 + 4 * sizeof(uint16_t) * x), uyva_hi);
133 }
134
135
4/4
void ToY416_sse2<false>(unsigned char*, int, unsigned char const*, int, unsigned char const*, unsigned char const*, int, unsigned char const*, int, int, int):
✓ Branch 41 → 40 taken 9 times.
✓ Branch 41 → 42 taken 3 times.
void ToY416_sse2<true>(unsigned char*, int, unsigned char const*, int, unsigned char const*, unsigned char const*, int, unsigned char const*, int, int, int):
✓ Branch 44 → 43 taken 9 times.
✓ Branch 44 → 45 taken 3 times.
24 for (int x = wmod4; x < width; x++) {
136 18 reinterpret_cast<uint16_t *>(outbuf)[x * 4 + 0] = reinterpret_cast<const uint16_t *>(uptr)[x];
137 18 reinterpret_cast<uint16_t *>(outbuf)[x * 4 + 1] = reinterpret_cast<const uint16_t *>(yptr)[x];
138 18 reinterpret_cast<uint16_t *>(outbuf)[x * 4 + 2] = reinterpret_cast<const uint16_t *>(vptr)[x];
139 18 reinterpret_cast<uint16_t *>(outbuf)[x * 4 + 3] = hasAlpha ? reinterpret_cast<const uint16_t *>(aptr)[x] : 0xFFFF;
140 }
141 6 outbuf += out_pitch;
142 6 yptr += ypitch;
143 6 uptr += uvpitch;
144 6 vptr += uvpitch;
145 6 aptr += apitch;
146 }
147 2 }
148
149 // instantiate
150 template void ToY416_sse2<false>(uint8_t *outbuf, int out_pitch, const uint8_t *yptr, int ypitch, const uint8_t *uptr, const uint8_t *vptr, int uvpitch, const uint8_t *aptr, int apitch, int width, int height);
151 template void ToY416_sse2<true>(uint8_t *outbuf, int out_pitch, const uint8_t *yptr, int ypitch, const uint8_t *uptr, const uint8_t *vptr, int uvpitch, const uint8_t *aptr, int apitch, int width, int height);
152 #endif
153
154 template<bool hasAlpha>
155 6 void ToY416_c(uint8_t *outbuf8, int out_pitch, const uint8_t *yptr, int ypitch, const uint8_t *uptr, const uint8_t *vptr, int uvpitch, const uint8_t *aptr, int apitch, int width, int height)
156 {
157 6 uint16_t *outbuf = reinterpret_cast<uint16_t *>(outbuf8);
158 6 out_pitch /= sizeof(uint16_t);
159
160
4/4
void ToY416_c<false>(unsigned char*, int, unsigned char const*, int, unsigned char const*, unsigned char const*, int, unsigned char const*, int, int, int):
✓ Branch 7 → 3 taken 9 times.
✓ Branch 7 → 8 taken 3 times.
void ToY416_c<true>(unsigned char*, int, unsigned char const*, int, unsigned char const*, unsigned char const*, int, unsigned char const*, int, int, int):
✓ Branch 7 → 3 taken 9 times.
✓ Branch 7 → 8 taken 3 times.
24 for (int y = 0; y < height; y++) {
161
4/4
void ToY416_c<false>(unsigned char*, int, unsigned char const*, int, unsigned char const*, unsigned char const*, int, unsigned char const*, int, int, int):
✓ Branch 5 → 4 taken 63 times.
✓ Branch 5 → 6 taken 9 times.
void ToY416_c<true>(unsigned char*, int, unsigned char const*, int, unsigned char const*, unsigned char const*, int, unsigned char const*, int, int, int):
✓ Branch 5 → 4 taken 63 times.
✓ Branch 5 → 6 taken 9 times.
144 for (int x = 0; x < width; x++) {
162 126 outbuf[x * 4 + 0] = reinterpret_cast<const uint16_t *>(uptr)[x];
163 126 outbuf[x * 4 + 1] = reinterpret_cast<const uint16_t *>(yptr)[x];
164 126 outbuf[x * 4 + 2] = reinterpret_cast<const uint16_t *>(vptr)[x];
165 126 outbuf[x * 4 + 3] = hasAlpha ? reinterpret_cast<const uint16_t *>(aptr)[x] : 0xFFFF;
166 }
167 18 outbuf += out_pitch;
168 18 yptr += ypitch;
169 18 uptr += uvpitch;
170 18 vptr += uvpitch;
171 18 aptr += apitch;
172 }
173 6 }
174 // instantiate
175 template void ToY416_c<false>(uint8_t *outbuf, int out_pitch, const uint8_t *yptr, int ypitch, const uint8_t *uptr, const uint8_t *vptr, int uvpitch, const uint8_t *aptr, int apitch, int width, int height);
176 template void ToY416_c<true>(uint8_t *outbuf, int out_pitch, const uint8_t *yptr, int ypitch, const uint8_t *uptr, const uint8_t *vptr, int uvpitch, const uint8_t *aptr, int apitch, int width, int height);
177
178 template<bool hasAlpha>
179 2 void FromY416_c(uint8_t *yptr, int ypitch, uint8_t *uptr, uint8_t *vptr, int uvpitch, uint8_t *aptr, int apitch,
180 const uint8_t *srcp8, int srcpitch,
181 int width, int height)
182 {
183 2 const uint16_t *srcp = reinterpret_cast<const uint16_t *>(srcp8);
184 2 srcpitch /= sizeof(uint16_t);
185
186
4/4
void FromY416_c<false>(unsigned char*, int, unsigned char*, unsigned char*, int, unsigned char*, int, unsigned char const*, int, int, int):
✓ Branch 8 → 3 taken 3 times.
✓ Branch 8 → 9 taken 1 time.
void FromY416_c<true>(unsigned char*, int, unsigned char*, unsigned char*, int, unsigned char*, int, unsigned char const*, int, int, int):
✓ Branch 7 → 3 taken 3 times.
✓ Branch 7 → 8 taken 1 time.
8 for (int y = 0; y < height; y++) {
187
4/4
void FromY416_c<false>(unsigned char*, int, unsigned char*, unsigned char*, int, unsigned char*, int, unsigned char const*, int, int, int):
✓ Branch 6 → 4 taken 21 times.
✓ Branch 6 → 7 taken 3 times.
void FromY416_c<true>(unsigned char*, int, unsigned char*, unsigned char*, int, unsigned char*, int, unsigned char const*, int, int, int):
✓ Branch 5 → 4 taken 21 times.
✓ Branch 5 → 6 taken 3 times.
48 for (int x = 0; x < width; x++) {
188 42 reinterpret_cast<uint16_t *>(uptr)[x] = srcp[x * 4 + 0];
189 42 reinterpret_cast<uint16_t *>(yptr)[x] = srcp[x * 4 + 1];
190 42 reinterpret_cast<uint16_t *>(vptr)[x] = srcp[x * 4 + 2];
191 if(hasAlpha)
192 21 reinterpret_cast<uint16_t *>(aptr)[x] = srcp[x * 4 + 3];
193 }
194 6 srcp += srcpitch;
195 6 yptr += ypitch;
196 6 uptr += uvpitch;
197 6 vptr += uvpitch;
198 6 aptr += apitch;
199 }
200 2 }
201 // instantiate
202 template void FromY416_c<false>(uint8_t *yptr, int ypitch, uint8_t *uptr, uint8_t *vptr, int uvpitch, uint8_t *aptr, int apitch, const uint8_t *srcp8, int srcpitch, int width, int height);
203 template void FromY416_c<true>(uint8_t *yptr, int ypitch, uint8_t *uptr, uint8_t *vptr, int uvpitch, uint8_t *aptr, int apitch, const uint8_t *srcp8, int srcpitch, int width, int height);
204
205 template<bool hasAlpha>
206 2 void ToY410_c(uint8_t* outbuf8, int out_pitch, const uint8_t* yptr, int ypitch, const uint8_t* uptr, const uint8_t* vptr, int uvpitch, const uint8_t* aptr, int apitch, int width, int height)
207 {
208 2 uint32_t* outbuf = reinterpret_cast<uint32_t*>(outbuf8);
209 2 out_pitch /= sizeof(uint32_t);
210
211
4/4
void ToY410_c<false>(unsigned char*, int, unsigned char const*, int, unsigned char const*, unsigned char const*, int, unsigned char const*, int, int, int):
✓ Branch 7 → 3 taken 3 times.
✓ Branch 7 → 8 taken 1 time.
void ToY410_c<true>(unsigned char*, int, unsigned char const*, int, unsigned char const*, unsigned char const*, int, unsigned char const*, int, int, int):
✓ Branch 7 → 3 taken 3 times.
✓ Branch 7 → 8 taken 1 time.
8 for (int y = 0; y < height; y++) {
212
4/4
void ToY410_c<false>(unsigned char*, int, unsigned char const*, int, unsigned char const*, unsigned char const*, int, unsigned char const*, int, int, int):
✓ Branch 5 → 4 taken 21 times.
✓ Branch 5 → 6 taken 3 times.
void ToY410_c<true>(unsigned char*, int, unsigned char const*, int, unsigned char const*, unsigned char const*, int, unsigned char const*, int, int, int):
✓ Branch 5 → 4 taken 21 times.
✓ Branch 5 → 6 taken 3 times.
48 for (int x = 0; x < width; x++) {
213 42 uint32_t uyva =
214 42 reinterpret_cast<const uint16_t*>(uptr)[x] +
215 42 (reinterpret_cast<const uint16_t*>(yptr)[x] << 10) +
216 42 (reinterpret_cast<const uint16_t*>(vptr)[x] << 20);
217 if constexpr(hasAlpha)
218 21 uyva += (reinterpret_cast<const uint16_t*>(aptr)[x] >> 8) << 30; // 2 bits only
219 else
220 21 uyva += 0x03 << 30; // 2 bits only
221 42 outbuf[x] = uyva;
222 }
223 6 outbuf += out_pitch;
224 6 yptr += ypitch;
225 6 uptr += uvpitch;
226 6 vptr += uvpitch;
227 6 aptr += apitch;
228 }
229 2 }
230 // instantiate
231 template void ToY410_c<false>(uint8_t* outbuf, int out_pitch, const uint8_t* yptr, int ypitch, const uint8_t* uptr, const uint8_t* vptr, int uvpitch, const uint8_t* aptr, int apitch, int width, int height);
232 template void ToY410_c<true>(uint8_t* outbuf, int out_pitch, const uint8_t* yptr, int ypitch, const uint8_t* uptr, const uint8_t* vptr, int uvpitch, const uint8_t* aptr, int apitch, int width, int height);
233
234 template<bool hasAlpha>
235 2 void FromY410_c(uint8_t* yptr, int ypitch, uint8_t* uptr, uint8_t* vptr, int uvpitch, uint8_t* aptr, int apitch,
236 const uint8_t* srcp8, int srcpitch,
237 int width, int height)
238 {
239 2 const uint32_t* srcp = reinterpret_cast<const uint32_t*>(srcp8);
240 2 srcpitch /= sizeof(uint32_t);
241
242
4/4
void FromY410_c<false>(unsigned char*, int, unsigned char*, unsigned char*, int, unsigned char*, int, unsigned char const*, int, int, int):
✓ Branch 7 → 3 taken 3 times.
✓ Branch 7 → 8 taken 1 time.
void FromY410_c<true>(unsigned char*, int, unsigned char*, unsigned char*, int, unsigned char*, int, unsigned char const*, int, int, int):
✓ Branch 10 → 3 taken 3 times.
✓ Branch 10 → 11 taken 1 time.
8 for (int y = 0; y < height; y++) {
243
4/4
void FromY410_c<false>(unsigned char*, int, unsigned char*, unsigned char*, int, unsigned char*, int, unsigned char const*, int, int, int):
✓ Branch 5 → 4 taken 21 times.
✓ Branch 5 → 6 taken 3 times.
void FromY410_c<true>(unsigned char*, int, unsigned char*, unsigned char*, int, unsigned char*, int, unsigned char const*, int, int, int):
✓ Branch 8 → 4 taken 21 times.
✓ Branch 8 → 9 taken 3 times.
48 for (int x = 0; x < width; x++) {
244 42 const uint32_t uyva = srcp[x];
245 42 reinterpret_cast<uint16_t*>(uptr)[x] = (uyva >> 0) & 0x3FF;
246 42 reinterpret_cast<uint16_t*>(yptr)[x] = (uyva >> 10) & 0x3FF;
247 42 reinterpret_cast<uint16_t*>(vptr)[x] = (uyva >> 20) & 0x3FF;
248 if constexpr(hasAlpha) {
249 21 const int alpha = (uyva >> 30) & 0x3;
250 // keep 03 as 3FF full transparent
251
2/2
✓ Branch 4 → 5 taken 17 times.
✓ Branch 4 → 6 taken 4 times.
21 reinterpret_cast<uint16_t*>(aptr)[x] = alpha == 3 ? 0x3FF : alpha << 8;
252 }
253 }
254 6 srcp += srcpitch;
255 6 yptr += ypitch;
256 6 uptr += uvpitch;
257 6 vptr += uvpitch;
258 6 aptr += apitch;
259 }
260 2 }
261 // instantiate
262 template void FromY410_c<false>(uint8_t* yptr, int ypitch, uint8_t* uptr, uint8_t* vptr, int uvpitch, uint8_t* aptr, int apitch, const uint8_t* srcp8, int srcpitch, int width, int height);
263 template void FromY410_c<true>(uint8_t* yptr, int ypitch, uint8_t* uptr, uint8_t* vptr, int uvpitch, uint8_t* aptr, int apitch, const uint8_t* srcp8, int srcpitch, int width, int height);
264
265 // Helpers for 10 bit RGB -> Planar RGB
266
267 static AVS_FORCEINLINE uint32_t avs_swap32(uint32_t x) {
268 30 x = (x & 0x0000FFFFu) << 16 | (x & 0xFFFF0000u) >> 16;
269 30 x = (x & 0x00FF00FFu) << 8 | (x & 0xFF00FF00u) >> 8;
270 30 return x;
271 }
272
273 1 void From_r210_c(uint8_t *rptr, uint8_t *gptr, uint8_t *bptr, int pitch, uint8_t *srcp8, int srcpitch, int width, int height)
274 {
275 // XXrrrrrr rrrrgggg ggggggbb bbbbbbbb
276 // BigEndian
277 1 const uint32_t *srcp = reinterpret_cast<const uint32_t *>(srcp8);
278 1 srcpitch /= sizeof(uint32_t);
279
280
2/2
✓ Branch 9 → 3 taken 3 times.
✓ Branch 9 → 10 taken 1 time.
4 for (int y = 0; y < height; y++) {
281
2/2
✓ Branch 7 → 4 taken 15 times.
✓ Branch 7 → 8 taken 3 times.
18 for (int x = 0; x < width; x++) {
282 15 const uint32_t rgb = avs_swap32(srcp[x]);
283 15 reinterpret_cast<uint16_t *>(bptr)[x] = (rgb >> 0) & 0x3FF;
284 15 reinterpret_cast<uint16_t *>(gptr)[x] = (rgb >> 10) & 0x3FF;
285 15 reinterpret_cast<uint16_t *>(rptr)[x] = (rgb >> 20) & 0x3FF;
286 }
287 3 srcp += srcpitch;
288 3 gptr += pitch;
289 3 rptr += pitch;
290 3 bptr += pitch;
291 }
292 1 }
293
294 1 void From_R10k_c(uint8_t *rptr, uint8_t *gptr, uint8_t *bptr, int pitch, uint8_t *srcp8, int srcpitch, int width, int height)
295 {
296 // rrrrrrrr rrgggggg ggggbbbb bbbbbbxx
297 // BigEndian
298 1 const uint32_t *srcp = reinterpret_cast<const uint32_t *>(srcp8);
299 1 srcpitch /= sizeof(uint32_t);
300
301
2/2
✓ Branch 9 → 3 taken 3 times.
✓ Branch 9 → 10 taken 1 time.
4 for (int y = 0; y < height; y++) {
302
2/2
✓ Branch 7 → 4 taken 15 times.
✓ Branch 7 → 8 taken 3 times.
18 for (int x = 0; x < width; x++) {
303 15 const uint32_t rgb = avs_swap32(srcp[x]);
304 15 reinterpret_cast<uint16_t *>(bptr)[x] = (rgb >> 2) & 0x3FF;
305 15 reinterpret_cast<uint16_t *>(gptr)[x] = (rgb >> 12) & 0x3FF;
306 15 reinterpret_cast<uint16_t *>(rptr)[x] = (rgb >> 22) & 0x3FF;
307 }
308 3 srcp += srcpitch;
309 3 gptr += pitch;
310 3 rptr += pitch;
311 3 bptr += pitch;
312 }
313 1 }
314
315 // Helpers for b64a <-> RGB64
316
317 static AVS_FORCEINLINE uint64_t avs_swap64(uint64_t x) {
318 60 x = (x & 0x00000000FFFFFFFFULL) << 32 | (x & 0xFFFFFFFF00000000ULL) >> 32;
319 60 x = (x & 0x0000FFFF0000FFFFULL) << 16 | (x & 0xFFFF0000FFFF0000ULL) >> 16;
320 60 x = (x & 0x00FF00FF00FF00FFULL) << 8 | (x & 0xFF00FF00FF00FF00ULL) >> 8;
321 60 return x;
322 }
323
324 #ifdef INTEL_INTRINSICS
325 #if defined(GCC) || defined(CLANG)
326 __attribute__((__target__("ssse3")))
327 #endif
328 static AVS_FORCEINLINE __m128i _mm_bswap_epi64_ssse3(__m128i x)
329 {
330 // Reverse order of bytes in each 64-bit word.
331 18 return _mm_shuffle_epi8(x, _mm_set_epi8(8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7));
332 }
333
334 static AVS_FORCEINLINE __m128i _mm_bswap_epi64_sse2(__m128i x)
335 {
336 // Reverse order of bytes in each 64-bit word.
337 // Swap bytes in each 16-bit word:
338 18 __m128i a = _mm_or_si128(
339 _mm_slli_epi16(x, 8),
340 _mm_srli_epi16(x, 8));
341
342 // Reverse all 16-bit words in 64-bit halves:
343 9 a = _mm_shufflelo_epi16(a, _MM_SHUFFLE(0, 1, 2, 3));
344 9 a = _mm_shufflehi_epi16(a, _MM_SHUFFLE(0, 1, 2, 3));
345
346 9 return a;
347 }
348 #endif // INTEL_INTRINSICS
349
350 static AVS_FORCEINLINE uint16_t avs_swap16(uint16_t x) {
351 45 return (x & 0x00FF) << 8 | (x & 0xFF00) >> 8;
352 }
353
354 // 3x1
355 1 void bgr_to_rgbBE_c(uint8_t* pdst, int dstpitch, const uint8_t *src, int srcpitch, int width, int height)
356 {
357 // todo sse2
358 // R G B R G B R G
359 // B R G B R G B R
360 // G B R G B R G B
361
362
2/2
✓ Branch 13 → 3 taken 3 times.
✓ Branch 13 → 14 taken 1 time.
4 for (int y = 0; y < height; y++) {
363
2/2
✓ Branch 11 → 4 taken 15 times.
✓ Branch 11 → 12 taken 3 times.
18 for (int x = 0; x < width; x++) {
364 15 uint16_t r = avs_swap16(reinterpret_cast<const uint16_t *>(src)[x * 3 + 0]);
365 15 uint16_t g = avs_swap16(reinterpret_cast<const uint16_t *>(src)[x * 3 + 1]);
366 15 uint16_t b = avs_swap16(reinterpret_cast<const uint16_t *>(src)[x * 3 + 2]);
367 15 reinterpret_cast<uint16_t*>(pdst)[x * 3 + 0] = b;
368 15 reinterpret_cast<uint16_t*>(pdst)[x * 3 + 1] = g;
369 15 reinterpret_cast<uint16_t*>(pdst)[x * 3 + 2] = r;
370 }
371 3 src += srcpitch;
372 3 pdst += dstpitch;
373 }
374 1 }
375
376 #ifdef INTEL_INTRINSICS
377 // 4x16: two-way symmetric
378 #if defined(GCC) || defined(CLANG)
379 __attribute__((__target__("ssse3")))
380 #endif
381 1 void bgra_to_argbBE_ssse3(uint8_t* pdst, int dstpitch, const uint8_t *src, int srcpitch, int width, int height)
382 {
383 // srcpitch or dstpitch may not be mod16
384 1 const int wmod2 = (width / 2) * 2; // 2x64bit
385
2/2
✓ Branch 31 → 3 taken 3 times.
✓ Branch 31 → 32 taken 1 time.
4 for (int y = 0; y < height; y++) {
386
2/2
✓ Branch 14 → 4 taken 6 times.
✓ Branch 14 → 15 taken 3 times.
9 for (int x = 0; x < wmod2; x += 2) {
387 12 __m128i a = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + 8 * x));
388 6 a = _mm_bswap_epi64_ssse3(a);
389 6 _mm_storeu_si128(reinterpret_cast<__m128i *>(pdst + 8 * x), a);
390 }
391
1/2
✓ Branch 15 → 16 taken 3 times.
✗ Branch 15 → 30 not taken.
3 if (wmod2 < width) {
392 6 __m128i a = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(src + 8 * wmod2));
393 3 a = _mm_bswap_epi64_ssse3(a);
394 3 _mm_storel_epi64(reinterpret_cast<__m128i *>(pdst + 8 * wmod2), a);
395 }
396 3 src += srcpitch;
397 3 pdst += dstpitch;
398 }
399 1 }
400
401 1 void bgra_to_argbBE_sse2(uint8_t* pdst, int dstpitch, const uint8_t *src, int srcpitch, int width, int height)
402 {
403 // dstpitch may not be mod16
404 1 const int wmod2 = (width / 2) * 2; // 2x64bit
405
2/2
✓ Branch 35 → 3 taken 3 times.
✓ Branch 35 → 36 taken 1 time.
4 for (int y = 0; y < height; y++) {
406
2/2
✓ Branch 16 → 4 taken 6 times.
✓ Branch 16 → 17 taken 3 times.
9 for (int x = 0; x < wmod2; x += 2) {
407 12 __m128i a = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + 8 * x));
408 6 a = _mm_bswap_epi64_sse2(a);
409 6 _mm_storeu_si128(reinterpret_cast<__m128i *>(pdst + 8 * x), a);
410 }
411
1/2
✓ Branch 17 → 18 taken 3 times.
✗ Branch 17 → 34 not taken.
3 if (wmod2 < width) {
412 6 __m128i a = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(src + 8 * wmod2));
413 3 a = _mm_bswap_epi64_sse2(a);
414 3 _mm_storel_epi64(reinterpret_cast<__m128i *>(pdst + 8 * wmod2), a);
415 }
416 3 src += srcpitch;
417 3 pdst += dstpitch;
418 }
419 1 }
420 #endif // INTEL_INTRINSICS
421
422 // 4x16: two-way symmetric
423 4 void bgra_to_argbBE_c(uint8_t* pdst, int dstpitch, const uint8_t *src, int srcpitch, int width, int height)
424 {
425
2/2
✓ Branch 9 → 3 taken 12 times.
✓ Branch 9 → 10 taken 4 times.
16 for (int y = 0; y < height; y++) {
426
2/2
✓ Branch 7 → 4 taken 60 times.
✓ Branch 7 → 8 taken 12 times.
72 for (int x = 0; x < width; x++) {
427 60 uint64_t a = reinterpret_cast<const uint64_t *>(src)[x]; // bgra -> argb+byte swap
428 60 a = avs_swap64(a);
429 60 reinterpret_cast<uint64_t*>(pdst)[x] = a;
430 }
431 12 src += srcpitch;
432 12 pdst += dstpitch;
433 }
434 4 }
435
436 // Helpers for YUV420(422)P10<->P010 and YUV420(422)P16<->P016 conversion
437
438 template<bool before>
439 static void prepare_luma_shift6_c(uint8_t* pdst, int dstpitch, const uint8_t *src, int srcpitch, int width, int height)
440 {
441 for (int y = 0; y < height; y++) {
442 for (int x = 0; x < width; x++) {
443 if (before)
444 reinterpret_cast<uint16_t*>(pdst)[x] = reinterpret_cast<const uint16_t *>(src)[x] << 6;
445 else
446 reinterpret_cast<uint16_t*>(pdst)[x] = reinterpret_cast<const uint16_t *>(src)[x] >> 6;
447 }
448 src += srcpitch;
449 pdst += dstpitch;
450 }
451 }
452
453 #ifdef INTEL_INTRINSICS
454 template<bool before>
455 2 static void prepare_luma_shift6_sse2(uint8_t* pdst, int dstpitch, const uint8_t *src, int srcpitch, int width, int height)
456 {
457 // srcpitch or dstpitch may not be mod16
458 2 const int modw = (width / 8) * 8; // 8 uv pairs at a time
459
4/4
void prepare_luma_shift6_sse2<false>(unsigned char*, int, unsigned char const*, int, int, int):
✓ Branch 16 → 3 taken 3 times.
✓ Branch 16 → 17 taken 1 time.
void prepare_luma_shift6_sse2<true>(unsigned char*, int, unsigned char const*, int, int, int):
✓ Branch 18 → 3 taken 3 times.
✓ Branch 18 → 19 taken 1 time.
8 for (int y = 0; y < height; y++) {
460
4/4
void prepare_luma_shift6_sse2<false>(unsigned char*, int, unsigned char const*, int, int, int):
✓ Branch 11 → 4 taken 6 times.
✓ Branch 11 → 12 taken 3 times.
void prepare_luma_shift6_sse2<true>(unsigned char*, int, unsigned char const*, int, int, int):
✓ Branch 12 → 4 taken 6 times.
✓ Branch 12 → 13 taken 3 times.
18 for (int x = 0; x < modw; x += 8) {
461 24 __m128i y = _mm_loadu_si128(reinterpret_cast<const __m128i *>(reinterpret_cast<const uint16_t *>(src) + x));
462 if (before)
463 6 y = _mm_slli_epi16(y, 6); // make 10->16 bits
464 else
465 6 y = _mm_srli_epi16(y, 6); // make 16->10 bits
466 12 _mm_storeu_si128(reinterpret_cast<__m128i *>(reinterpret_cast<uint16_t *>(pdst) + x), y);
467 }
468
469
4/4
void prepare_luma_shift6_sse2<false>(unsigned char*, int, unsigned char const*, int, int, int):
✓ Branch 14 → 13 taken 6 times.
✓ Branch 14 → 15 taken 3 times.
void prepare_luma_shift6_sse2<true>(unsigned char*, int, unsigned char const*, int, int, int):
✓ Branch 16 → 14 taken 6 times.
✓ Branch 16 → 17 taken 3 times.
18 for (int x = modw; x < width; x++) {
470 if (before)
471 6 reinterpret_cast<uint16_t*>(pdst)[x] = reinterpret_cast<const uint16_t *>(src)[x] << 6;
472 else
473 6 reinterpret_cast<uint16_t*>(pdst)[x] = reinterpret_cast<const uint16_t *>(src)[x] >> 6;
474 }
475 6 src += srcpitch;
476 6 pdst += dstpitch;
477 }
478 2 }
479 #endif // INTEL_INTRINSICS
480
481 template<bool shift6>
482 static void prepare_to_interleaved_uv_c(uint8_t* pdst, int dstpitch, const uint8_t *srcu, const uint8_t *srcv, int pitchUV, int width, int height)
483 {
484 for (int y = 0; y < height; y++) {
485 for (int x = 0; x < width; x++) {
486 uint16_t u, v;
487 if (shift6) {
488 u = reinterpret_cast<const uint16_t *>(srcu)[x] << 6; // make 10->16 bits
489 v = reinterpret_cast<const uint16_t *>(srcv)[x] << 6; // make 10->16 bits
490 }
491 else {
492 u = reinterpret_cast<const uint16_t *>(srcu)[x];
493 v = reinterpret_cast<const uint16_t *>(srcv)[x];
494 }
495 uint32_t uv = (v << 16) | u;
496 reinterpret_cast<uint32_t*>(pdst)[x] = uv;
497 }
498 srcu += pitchUV;
499 srcv += pitchUV;
500 pdst += dstpitch;
501 }
502 }
503
504 #ifdef INTEL_INTRINSICS
505 template<bool shift6>
506 2 static void prepare_to_interleaved_uv_sse2(uint8_t* pdst, int dstpitch, const uint8_t *srcu, const uint8_t *srcv, int pitchUV, int width, int height)
507 {
508 // dstpitch may not be mod16
509 2 const int modw = (width / 8) * 8; // 8 uv pairs at a time
510
4/4
void prepare_to_interleaved_uv_sse2<false>(unsigned char*, int, unsigned char const*, unsigned char const*, int, int, int):
✓ Branch 21 → 3 taken 3 times.
✓ Branch 21 → 22 taken 1 time.
void prepare_to_interleaved_uv_sse2<true>(unsigned char*, int, unsigned char const*, unsigned char const*, int, int, int):
✓ Branch 25 → 3 taken 3 times.
✓ Branch 25 → 26 taken 1 time.
8 for (int y = 0; y < height; y++) {
511
4/4
void prepare_to_interleaved_uv_sse2<false>(unsigned char*, int, unsigned char const*, unsigned char const*, int, int, int):
✓ Branch 16 → 4 taken 3 times.
✓ Branch 16 → 17 taken 3 times.
void prepare_to_interleaved_uv_sse2<true>(unsigned char*, int, unsigned char const*, unsigned char const*, int, int, int):
✓ Branch 19 → 4 taken 3 times.
✓ Branch 19 → 20 taken 3 times.
12 for (int x = 0; x < modw; x += 8) {
512 6 __m128i u = _mm_load_si128(reinterpret_cast<const __m128i *>(reinterpret_cast<const uint16_t *>(srcu) + x));
513 12 __m128i v = _mm_load_si128(reinterpret_cast<const __m128i *>(reinterpret_cast<const uint16_t *>(srcv) + x));
514 if (shift6) {
515 3 u = _mm_slli_epi16(u, 6); // make 10->16 bits
516 3 v = _mm_slli_epi16(v, 6);
517 }
518 __m128i uv;
519 6 uv = _mm_unpacklo_epi16(u, v); // (v << 16) | u;
520 6 _mm_storeu_si128(reinterpret_cast<__m128i *>(reinterpret_cast<uint32_t *>(pdst) + x), uv);
521 6 uv = _mm_unpackhi_epi16(u, v); // (v << 16) | u;
522 6 _mm_storeu_si128(reinterpret_cast<__m128i *>(reinterpret_cast<uint32_t *>(pdst) + x + 4), uv);
523 }
524
525
4/4
void prepare_to_interleaved_uv_sse2<false>(unsigned char*, int, unsigned char const*, unsigned char const*, int, int, int):
✓ Branch 19 → 18 taken 3 times.
✓ Branch 19 → 20 taken 3 times.
void prepare_to_interleaved_uv_sse2<true>(unsigned char*, int, unsigned char const*, unsigned char const*, int, int, int):
✓ Branch 23 → 21 taken 3 times.
✓ Branch 23 → 24 taken 3 times.
12 for (int x = modw; x < width; x++) {
526 uint16_t u, v;
527 if (shift6) {
528 3 u = reinterpret_cast<const uint16_t *>(srcu)[x] << 6; // make 10->16 bits
529 3 v = reinterpret_cast<const uint16_t *>(srcv)[x] << 6; // make 10->16 bits
530 }
531 else {
532 3 u = reinterpret_cast<const uint16_t *>(srcu)[x];
533 3 v = reinterpret_cast<const uint16_t *>(srcv)[x];
534 }
535 6 uint32_t uv = (v << 16) | u;
536 6 reinterpret_cast<uint32_t*>(pdst)[x] = uv;
537 }
538 6 srcu += pitchUV;
539 6 srcv += pitchUV;
540 6 pdst += dstpitch;
541 }
542 2 }
543 #endif // INTEL_INTRINSICS
544
545 template<bool shift6>
546 static void prepare_from_interleaved_uv_c(uint8_t* pdstu, uint8_t* pdstv, int pitchUV, const uint8_t *src, int srcpitch, int width, int height)
547 {
548 for (int y = 0; y < height; y++) {
549 for (int x = 0; x < width; x++) {
550 uint32_t uv = reinterpret_cast<const uint32_t*>(src)[x];
551 uint16_t u = uv & 0xFFFF;
552 uint16_t v = uv >> 16;
553 if (shift6) {
554 u >>= 6;
555 v >>= 6;
556 }
557 reinterpret_cast<uint16_t*>(pdstu)[x] = u;
558 reinterpret_cast<uint16_t*>(pdstv)[x] = v;
559 }
560 pdstu += pitchUV;
561 pdstv += pitchUV;
562 src += srcpitch;
563 }
564 }
565
566 #ifdef INTEL_INTRINSICS
567 template<bool shift6>
568 static void prepare_from_interleaved_uv_sse2(uint8_t* pdstu, uint8_t* pdstv, int pitchUV, const uint8_t *src, int srcpitch, int width, int height)
569 {
570 // srcpitch may not be mod16
571 const int modw = (width / 8) * 8;
572 auto mask0000FFFF = _mm_set1_epi32(0x0000FFFF);
573 for (int y = 0; y < height; y++) {
574 for (int x = 0; x < modw; x += 8) {
575 auto uv_lo = _mm_loadu_si128(reinterpret_cast<const __m128i *>(reinterpret_cast<const uint32_t*>(src) + x));
576 auto uv_hi = _mm_loadu_si128(reinterpret_cast<const __m128i *>(reinterpret_cast<const uint32_t*>(src) + x + 4));
577 if (shift6) {
578 uv_lo = _mm_srli_epi16(uv_lo, 6);
579 uv_hi = _mm_srli_epi16(uv_hi, 6);
580 }
581 auto u_lo = _mm_and_si128(uv_lo, mask0000FFFF);
582 auto u_hi = _mm_and_si128(uv_hi, mask0000FFFF);
583 auto u = shift6 ? _mm_packs_epi32(u_lo, u_hi) : _MM_PACKUS_EPI32(u_lo, u_hi); // sse41 simul
584 _mm_store_si128(reinterpret_cast<__m128i *>(reinterpret_cast<uint16_t*>(pdstu) + x), u);
585
586 auto v_lo = _mm_srli_epi32(uv_lo, 16);
587 auto v_hi = _mm_srli_epi32(uv_hi, 16);
588 auto v = shift6 ? _mm_packs_epi32(v_lo, v_hi) : _MM_PACKUS_EPI32(v_lo, v_hi); // sse41 simul
589 _mm_store_si128(reinterpret_cast<__m128i *>(reinterpret_cast<uint16_t*>(pdstv) + x), v);
590 }
591
592 for (int x = modw; x < width; x++) {
593 uint32_t uv = reinterpret_cast<const uint32_t*>(src)[x];
594 uint16_t u = uv & 0xFFFF;
595 uint16_t v = uv >> 16;
596 if (shift6) {
597 u >>= 6;
598 v >>= 6;
599 }
600 reinterpret_cast<uint16_t*>(pdstu)[x] = u;
601 reinterpret_cast<uint16_t*>(pdstv)[x] = v;
602 }
603
604 pdstu += pitchUV;
605 pdstv += pitchUV;
606 src += srcpitch;
607 }
608 }
609
610 template<bool shift6>
611 #if defined(GCC) || defined(CLANG)
612 __attribute__((__target__("sse4.1")))
613 #endif
614 2 static void prepare_from_interleaved_uv_sse41(uint8_t* pdstu, uint8_t* pdstv, int pitchUV, const uint8_t *src, int srcpitch, int width, int height)
615 {
616 // srcpitch may not be mod16
617 2 const int modw = (width / 8) * 8;
618 2 auto mask0000FFFF = _mm_set1_epi32(0x0000FFFF);
619
4/4
void prepare_from_interleaved_uv_sse41<false>(unsigned char*, unsigned char*, int, unsigned char const*, int, int, int):
✓ Branch 34 → 7 taken 3 times.
✓ Branch 34 → 35 taken 1 time.
void prepare_from_interleaved_uv_sse41<true>(unsigned char*, unsigned char*, int, unsigned char const*, int, int, int):
✓ Branch 36 → 7 taken 3 times.
✓ Branch 36 → 37 taken 1 time.
8 for (int y = 0; y < height; y++) {
620
4/4
void prepare_from_interleaved_uv_sse41<false>(unsigned char*, unsigned char*, int, unsigned char const*, int, int, int):
✓ Branch 28 → 8 taken 3 times.
✓ Branch 28 → 29 taken 3 times.
void prepare_from_interleaved_uv_sse41<true>(unsigned char*, unsigned char*, int, unsigned char const*, int, int, int):
✓ Branch 31 → 8 taken 3 times.
✓ Branch 31 → 32 taken 3 times.
12 for (int x = 0; x < modw; x += 8) {
621 6 auto uv_lo = _mm_loadu_si128(reinterpret_cast<const __m128i *>(reinterpret_cast<const uint32_t*>(src) + x));
622 12 auto uv_hi = _mm_loadu_si128(reinterpret_cast<const __m128i *>(reinterpret_cast<const uint32_t*>(src) + x + 4));
623 if (shift6) {
624 3 uv_lo = _mm_srli_epi16(uv_lo, 6);
625 3 uv_hi = _mm_srli_epi16(uv_hi, 6);
626 }
627 6 auto u_lo = _mm_and_si128(uv_lo, mask0000FFFF);
628 6 auto u_hi = _mm_and_si128(uv_hi, mask0000FFFF);
629 6 auto u = shift6 ? _mm_packs_epi32(u_lo, u_hi) : _mm_packus_epi32(u_lo, u_hi); // sse41
630 6 _mm_store_si128(reinterpret_cast<__m128i *>(reinterpret_cast<uint16_t*>(pdstu) + x), u);
631
632 6 auto v_lo = _mm_srli_epi32(uv_lo, 16);
633 6 auto v_hi = _mm_srli_epi32(uv_hi, 16);
634 6 auto v = shift6 ? _mm_packs_epi32(v_lo, v_hi) : _mm_packus_epi32(v_lo, v_hi); // sse41
635 6 _mm_store_si128(reinterpret_cast<__m128i *>(reinterpret_cast<uint16_t*>(pdstv) + x), v);
636 }
637
638
4/4
void prepare_from_interleaved_uv_sse41<false>(unsigned char*, unsigned char*, int, unsigned char const*, int, int, int):
✓ Branch 32 → 30 taken 3 times.
✓ Branch 32 → 33 taken 3 times.
void prepare_from_interleaved_uv_sse41<true>(unsigned char*, unsigned char*, int, unsigned char const*, int, int, int):
✓ Branch 34 → 33 taken 3 times.
✓ Branch 34 → 35 taken 3 times.
12 for (int x = modw; x < width; x++) {
639 6 uint32_t uv = reinterpret_cast<const uint32_t*>(src)[x];
640 6 uint16_t u = uv & 0xFFFF;
641 6 uint16_t v = uv >> 16;
642 if (shift6) {
643 3 u >>= 6;
644 3 v >>= 6;
645 }
646 6 reinterpret_cast<uint16_t*>(pdstu)[x] = u;
647 6 reinterpret_cast<uint16_t*>(pdstv)[x] = v;
648 }
649
650 6 pdstu += pitchUV;
651 6 pdstv += pitchUV;
652 6 src += srcpitch;
653 }
654 2 }
655 #endif // INTEL_INTRINSICS
656
657
658 1 void yuv422p10_to_v210(BYTE *dstp, const BYTE *srcp_y, int srcpitch, const BYTE *srcp_u, const BYTE *srcp_v, int srcpitch_uv, int width, int height)
659 {
660 1 int ppitch_y = srcpitch / sizeof(uint16_t);
661 1 int ppitch_uv = srcpitch_uv / sizeof(uint16_t);
662 1 const uint16_t *yptr = (const uint16_t *)srcp_y;
663 1 const uint16_t *uptr = (const uint16_t *)srcp_u;
664 1 const uint16_t *vptr = (const uint16_t *)srcp_v;
665 1 uint32_t *outbuf = (uint32_t *)dstp;
666 1 const int out_pitch = ((16 * ((width + 5) / 6) + 127) & ~127) / 4;
667
2/2
✓ Branch 7 → 3 taken 3 times.
✓ Branch 7 → 8 taken 1 time.
4 for (int y = 0; y < height; y++) {
668 3 const uint16_t *yline = yptr;
669 3 const uint16_t *uline = uptr;
670 3 const uint16_t *vline = vptr;
671 3 uint32_t *out_line = outbuf;
672
2/2
✓ Branch 5 → 4 taken 9 times.
✓ Branch 5 → 6 taken 3 times.
12 for (int x = 0; x < width + 5; x += 6) {
673 9 out_line[0] = (uline[0] | (yline[0] << 10) | (vline[0] << 20));
674 9 out_line[1] = (yline[1] | (uline[1] << 10) | (yline[2] << 20));
675 9 out_line[2] = (vline[1] | (yline[3] << 10) | (uline[2] << 20));
676 9 out_line[3] = (yline[4] | (vline[2] << 10) | (yline[5] << 20));
677 9 out_line += 4;
678 9 yline += 6;
679 9 uline += 3;
680 9 vline += 3;
681 }
682 3 outbuf += out_pitch;
683 3 yptr += ppitch_y;
684 3 uptr += ppitch_uv;
685 3 vptr += ppitch_uv;
686 }
687 1 }
688
689
690 1 void v210_to_yuv422p10(BYTE *dstp_y, int dstpitch, BYTE *dstp_u, BYTE *dstp_v, int dstpitch_uv, const BYTE *srcp, int width, int height)
691 {
692 /*
693 v210: packed YUV 4:2:2 (UYVY) 10 bits per component.
694 Data is stored in blocks of 32 bit values in little-endian.
695 Each such block contains 3 components, one each in bits 0 - 9, 10 - 19 and 20 - 29, the remaining two bits are unused.
696 Six pixels in a pattern that repeats every 4 32-bits blocks:
697
698 block 1, bits 0 - 9: U0-1
699 block 1, bits 10 - 19: Y0
700 block 1, bits 20 - 29: V0-1
701 block 2, bits 0 - 9: Y1
702 block 2, bits 10 - 19: U2-3
703 block 2, bits 20 - 29: Y2
704 block 3, bits 0 - 9: V2-3
705 block 3, bits 10 - 19: Y3
706 block 3, bits 20 - 29: U4-5
707 block 4, bits 0 - 9: Y4
708 block 4, bits 10 - 19: V4-5
709 block 4, bits 20 - 29: Y5
710
711 */
712 1 int ppitch_y = dstpitch / sizeof(uint16_t);
713 1 int ppitch_uv = dstpitch_uv / sizeof(uint16_t);
714 1 uint16_t *yptr = (uint16_t *)dstp_y;
715 1 uint16_t *uptr = (uint16_t *)dstp_u;
716 1 uint16_t *vptr = (uint16_t *)dstp_v;
717
718 1 const int srcpitch = ((16 * ((width + 5) / 6) + 127) & ~127);
719
720 1 const int width6 = (width / 6) * 6;
721 1 const int width_rest = width - width6;
722
723
2/2
✓ Branch 10 → 3 taken 3 times.
✓ Branch 10 → 11 taken 1 time.
4 for (int y = 0; y < height; y++) {
724 3 uint16_t *yline = yptr;
725 3 uint16_t *uline = uptr;
726 3 uint16_t *vline = vptr;
727 3 const uint32_t *srcline = reinterpret_cast<const uint32_t *>(srcp);
728
729
2/2
✓ Branch 5 → 4 taken 3 times.
✓ Branch 5 → 6 taken 3 times.
6 for (int x = 0; x < width6; x += 6) {
730 3 uint32_t block1 = srcline[0];
731 3 uint32_t block2 = srcline[1];
732 3 uint32_t block3 = srcline[2];
733 3 uint32_t block4 = srcline[3];
734
735 3 uline[0] = (block1) & 0x3FF;
736 3 vline[0] = (block1 >> 20) & 0x3FF;
737 3 yline[0] = (block1 >> 10) & 0x3FF;
738 3 yline[1] = (block2) & 0x3FF;
739
740 3 uline[1] = (block2 >> 10) & 0x3FF;
741 3 vline[1] = (block3) & 0x3FF;
742 3 yline[2] = (block2 >> 20) & 0x3FF;
743 3 yline[3] = (block3 >> 10) & 0x3FF;
744
745 3 uline[2] = (block3 >> 20) & 0x3FF;
746 3 vline[2] = (block4 >> 10) & 0x3FF;
747 3 yline[4] = (block4) & 0x3FF;
748 3 yline[5] = (block4 >> 20) & 0x3FF;
749
750 3 srcline += 4;
751 3 yline += 6;
752 3 uline += 3;
753 3 vline += 3;
754 }
755 // rest 2 or 4 pixels
756
1/2
✓ Branch 6 → 7 taken 3 times.
✗ Branch 6 → 9 not taken.
3 if (width_rest >= 2) {
757 3 uint32_t block1 = srcline[0];
758 3 uint32_t block2 = srcline[1];
759
760 3 uline[0] = (block1) & 0x3FF;
761 3 vline[0] = (block1 >> 20) & 0x3FF;
762 3 yline[0] = (block1 >> 10) & 0x3FF;
763 3 yline[1] = (block2) & 0x3FF;
764
765
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 3 times.
3 if (width_rest >= 4) {
766 uint32_t block3 = srcline[2];
767
768 uline[1] = (block2 >> 10) & 0x3FF;
769 vline[1] = (block3) & 0x3FF;
770 yline[2] = (block2 >> 20) & 0x3FF;
771 yline[3] = (block3 >> 10) & 0x3FF;
772 }
773 }
774 3 srcp += srcpitch;
775 3 yptr += ppitch_y;
776 3 uptr += ppitch_uv;
777 3 vptr += ppitch_uv;
778 }
779 1 }
780
781 1 void v408_to_yuva444p8(BYTE* dstp_y, int dstpitch, BYTE* dstp_u, BYTE* dstp_v, BYTE* dstp_a, int dstpitch_uv, int dstpitch_a, const BYTE* srcp, int width, int height)
782 {
783 1 int ppitch_y = dstpitch;
784 1 int ppitch_uv = dstpitch_uv;
785 1 int ppitch_a = dstpitch_a;
786 1 uint8_t* yptr = dstp_y;
787 1 uint8_t* uptr = dstp_u;
788 1 uint8_t* vptr = dstp_v;
789 1 uint8_t* aptr = dstp_a;
790
791 1 const int srcpitch = width * 4;
792
793
2/2
✓ Branch 7 → 3 taken 3 times.
✓ Branch 7 → 8 taken 1 time.
4 for (int y = 0; y < height; y++) {
794 3 uint8_t* yline = yptr;
795 3 uint8_t* uline = uptr;
796 3 uint8_t* vline = vptr;
797 3 uint8_t* aline = aptr;
798 3 const uint32_t* srcline = reinterpret_cast<const uint32_t*>(srcp);
799
800
2/2
✓ Branch 5 → 4 taken 21 times.
✓ Branch 5 → 6 taken 3 times.
24 for (int x = 0; x < width; x++) {
801 21 uint32_t block = srcline[x]; // 4x8 bit
802 21 uline[x] = (block) & 0xFF;
803 21 vline[x] = (block >> 16) & 0xFF;
804 21 yline[x] = (block >> 8) & 0xFF;
805 21 aline[x] = (block >> 24) & 0xFF;
806 }
807 3 srcp += srcpitch;
808 3 yptr += ppitch_y;
809 3 uptr += ppitch_uv;
810 3 vptr += ppitch_uv;
811 3 aptr += ppitch_a;
812 }
813 1 }
814
815 1 void v308_to_yuv444p8(BYTE* dstp_y, int dstpitch, BYTE* dstp_u, BYTE* dstp_v, int dstpitch_uv, const BYTE* srcp, int width, int height)
816 {
817 1 int ppitch_y = dstpitch;
818 1 int ppitch_uv = dstpitch_uv;
819 1 uint8_t* yptr = dstp_y;
820 1 uint8_t* uptr = dstp_u;
821 1 uint8_t* vptr = dstp_v;
822
823 1 const int srcpitch = width * 3;
824
825
2/2
✓ Branch 7 → 3 taken 3 times.
✓ Branch 7 → 8 taken 1 time.
4 for (int y = 0; y < height; y++) {
826 3 uint8_t* yline = yptr;
827 3 uint8_t* uline = uptr;
828 3 uint8_t* vline = vptr;
829 3 const uint8_t* srcline = srcp;
830
831
2/2
✓ Branch 5 → 4 taken 21 times.
✓ Branch 5 → 6 taken 3 times.
24 for (int x = 0; x < width; x++) {
832 21 vline[x] = srcline[x * 3 + 0];
833 21 yline[x] = srcline[x * 3 + 1];
834 21 uline[x] = srcline[x * 3 + 2];
835 }
836 3 srcp += srcpitch;
837 3 yptr += ppitch_y;
838 3 uptr += ppitch_uv;
839 3 vptr += ppitch_uv;
840 }
841 1 }
842
843 1 void v410_to_yuv444p10(BYTE* dstp_y, int dstpitch, BYTE* dstp_u, BYTE* dstp_v, int dstpitch_uv, const BYTE* srcp, int width, int height)
844 {
845 1 int ppitch_y = dstpitch / sizeof(uint16_t);
846 1 int ppitch_uv = dstpitch_uv / sizeof(uint16_t);
847 1 uint16_t* yptr = (uint16_t*)dstp_y;
848 1 uint16_t* uptr = (uint16_t*)dstp_u;
849 1 uint16_t* vptr = (uint16_t*)dstp_v;
850
851 1 const int srcpitch = width * 4;
852
853
2/2
✓ Branch 7 → 3 taken 3 times.
✓ Branch 7 → 8 taken 1 time.
4 for (int y = 0; y < height; y++) {
854 3 uint16_t* yline = yptr;
855 3 uint16_t* uline = uptr;
856 3 uint16_t* vline = vptr;
857 3 const uint32_t* srcline = reinterpret_cast<const uint32_t*>(srcp);
858
859
2/2
✓ Branch 5 → 4 taken 21 times.
✓ Branch 5 → 6 taken 3 times.
24 for (int x = 0; x < width; x++) {
860 21 uint32_t block = srcline[x];
861
862 21 yline[x] = (block >> 12) & 0x3FF;
863 21 uline[x] = (block >> 2) & 0x3FF;
864 21 vline[x] = (block >> 22) & 0x3FF;
865 }
866 3 srcp += srcpitch;
867 3 yptr += ppitch_y;
868 3 uptr += ppitch_uv;
869 3 vptr += ppitch_uv;
870 }
871 1 }
872
873 2 void yuv42xp10_16_to_Px10_16(BYTE *dstp, int dstpitch, const BYTE *srcp_y, int srcpitch,
874 const BYTE *srcp_u, const BYTE *srcp_v, int srcpitch_uv,
875 int width, int height, int cheight, bool semi_packed_p16, IScriptEnvironment *env)
876 {
877 // P010/P016/P210/P216 format:
878 // Single buffer
879 // n lines YYYYYYYYYYYYYY
880 // n/2 lines UVUVUVUVUVUVUV (4:2:0)
881 // or n lines UVUVUVUVUVUVUV (4:2:2)
882 // Pitch is common. P010/P210 is upshifted to 16 bits
883
884 #ifdef INTEL_INTRINSICS
885 2 const bool sse2 = !!(env->GetCPUFlags() & CPUF_SSE2);
886 #endif
887
888 // dstpitch may not be mod16
889
890 // luma
891
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 1 time.
2 if (semi_packed_p16) {
892 // no shift, native copy
893 1 env->BitBlt(dstp, dstpitch, srcp_y, srcpitch, width * sizeof(uint16_t), height);
894 }
895 else {
896 // shift by 6 make 10->16 bits
897 #ifdef INTEL_INTRINSICS
898
1/2
✓ Branch 5 → 6 taken 1 time.
✗ Branch 5 → 7 not taken.
1 if (sse2)
899 1 prepare_luma_shift6_sse2<true>(dstp, dstpitch, srcp_y, srcpitch, width, height); // true: conv to P016
900 else
901 #endif // INTEL_INTRINSICS
902 prepare_luma_shift6_c<true>(dstp, dstpitch, srcp_y, srcpitch, width, height); // true: conv to P016
903 }
904
905 2 dstp += dstpitch * height;
906
907 // Chroma
908 2 int cwidth = width / 2;
909
910 #ifdef INTEL_INTRINSICS
911
1/2
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 12 not taken.
2 if (sse2) {
912
2/2
✓ Branch 9 → 10 taken 1 time.
✓ Branch 9 → 11 taken 1 time.
2 if (semi_packed_p16)
913 1 prepare_to_interleaved_uv_sse2<false>(dstp, dstpitch, srcp_u, srcp_v, srcpitch_uv, cwidth, cheight);
914 else
915 1 prepare_to_interleaved_uv_sse2<true>(dstp, dstpitch, srcp_u, srcp_v, srcpitch_uv, cwidth, cheight); // shift6 inside
916 }
917 else {
918 #endif // INTEL_INTRINSICS
919 if (semi_packed_p16)
920 prepare_to_interleaved_uv_c<false>(dstp, dstpitch, srcp_u, srcp_v, srcpitch_uv, cwidth, cheight);
921 else
922 prepare_to_interleaved_uv_c<true>(dstp, dstpitch, srcp_u, srcp_v, srcpitch_uv, cwidth, cheight); // shift6 inside
923 #ifdef INTEL_INTRINSICS
924 }
925 #endif // INTEL_INTRINSICS
926
927 2 }
928
929 2 void Px10_16_to_yuv42xp10_16(BYTE *dstp_y, int dstpitch, BYTE *dstp_u, BYTE *dstp_v, int dstpitch_uv,
930 const BYTE *srcp, int srcpitch,
931 int width, int height, int cheight, bool semi_packed_p16, IScriptEnvironment *env)
932 {
933 #ifdef INTEL_INTRINSICS
934 2 const bool sse2 = !!(env->GetCPUFlags() & CPUF_SSE2);
935 2 const bool sse41 = !!(env->GetCPUFlags() & CPUF_SSE4_1);
936 #endif
937
938 // srcpitch may not be mod16
939
940 // convert P010, P016, P210 and P216 formats back to Avisynth YUV420P10 and P16 or YUV422P10 and P16 formats
941
942 // Luma
943
2/2
✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 1 time.
2 if (semi_packed_p16) {
944 1 env->BitBlt(dstp_y, dstpitch, srcp, srcpitch, width * sizeof(uint16_t), height);
945 }
946 else {
947 // shift by 6 make 10->16 bits
948 #ifdef INTEL_INTRINSICS
949
1/2
✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 8 not taken.
1 if (sse2)
950 1 prepare_luma_shift6_sse2<false>(dstp_y, dstpitch, srcp, srcpitch, width, height); // false: after
951 else
952 #endif
953 prepare_luma_shift6_c<false>(dstp_y, dstpitch, srcp, srcpitch, width, height); // false: after
954 }
955 2 srcp += srcpitch * height;
956
957 // Chroma
958 2 int cwidth = width / 2; // 422 or 420
959 #ifdef INTEL_INTRINSICS
960
1/2
✓ Branch 9 → 10 taken 2 times.
✗ Branch 9 → 13 not taken.
2 if (sse41) {
961
2/2
✓ Branch 10 → 11 taken 1 time.
✓ Branch 10 → 12 taken 1 time.
2 if (semi_packed_p16)
962 1 prepare_from_interleaved_uv_sse41<false>(dstp_u, dstp_v, dstpitch_uv, srcp, srcpitch, cwidth, cheight);
963 else
964 1 prepare_from_interleaved_uv_sse41<true>(dstp_u, dstp_v, dstpitch_uv, srcp, srcpitch, cwidth, cheight); // true: shift 6
965 }
966 else if (sse2) {
967 if (semi_packed_p16)
968 prepare_from_interleaved_uv_sse2<false>(dstp_u, dstp_v, dstpitch_uv, srcp, srcpitch, cwidth, cheight);
969 else
970 prepare_from_interleaved_uv_sse2<true>(dstp_u, dstp_v, dstpitch_uv, srcp, srcpitch, cwidth, cheight); // true: shift 6
971 }
972 else {
973 #endif // INTEL_INTRINSICS
974 if (semi_packed_p16)
975 prepare_from_interleaved_uv_c<false>(dstp_u, dstp_v, dstpitch_uv, srcp, srcpitch, cwidth, cheight);
976 else
977 prepare_from_interleaved_uv_c<true>(dstp_u, dstp_v, dstpitch_uv, srcp, srcpitch, cwidth, cheight); // true: shift 6
978 #ifdef INTEL_INTRINSICS
979 }
980 #endif
981 2 }
982
983