Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qvideoframeconversionhelper.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5#include "qrgb.h"
6
7#include <mutex>
8
9QT_BEGIN_NAMESPACE
10
11#define CLAMP(n) (n > 255 ? 255 : (n < 0 ? 0 : n))
12
13#define EXPAND_UV(u, v)
14 int uu = u - 128;
15 int vv = v - 128;
16 int rv = 409 * vv + 128;
17 int guv = 100 * uu + 208 * vv + 128;
18 int bu = 516 * uu + 128;
19
20static inline quint32 qYUVToARGB32(int y, int rv, int guv, int bu, int a = 0xff)
21{
22 int yy = (y - 16) * 298;
23 return (a << 24)
24 | CLAMP((yy + rv) >> 8) << 16
25 | CLAMP((yy - guv) >> 8) << 8
26 | CLAMP((yy + bu) >> 8);
27}
28
29static inline void planarYUV420_to_ARGB32(const uchar *y, int yStride,
30 const uchar *u, int uStride,
31 const uchar *v, int vStride,
32 int uvPixelStride,
33 quint32 *rgb,
34 int width, int height)
35{
36 height &= ~1;
37
38 for (int j = 0; j + 1 < height; j += 2) {
39 const uchar *lineY0 = y;
40 const uchar *lineY1 = y + yStride;
41 const uchar *lineU = u;
42 const uchar *lineV = v;
43
44 quint32 *rgb0 = rgb;
45 quint32 *rgb1 = rgb + width;
46 for (int i = 0; i + 1 < width; i += 2) {
47 EXPAND_UV(*lineU, *lineV);
48 lineU += uvPixelStride;
49 lineV += uvPixelStride;
50
51 rgb0[i] = qYUVToARGB32(*lineY0++, rv, guv, bu);
52 rgb0[i + 1] = qYUVToARGB32(*lineY0++, rv, guv, bu);
53 rgb1[i] = qYUVToARGB32(*lineY1++, rv, guv, bu);
54 rgb1[i + 1] = qYUVToARGB32(*lineY1++, rv, guv, bu);
55 }
56
57 y += yStride << 1; // stride * 2
58 u += uStride;
59 v += vStride;
60 rgb += width << 1; // width * 2
61 }
62}
63
64static inline void planarYUV422_to_ARGB32(const uchar *y, int yStride,
65 const uchar *u, int uStride,
66 const uchar *v, int vStride,
67 int uvPixelStride,
68 quint32 *rgb,
69 int width, int height)
70{
71 for (int j = 0; j < height; ++j) {
72 const uchar *lineY0 = y;
73 const uchar *lineU = u;
74 const uchar *lineV = v;
75
76 for (int i = 0; i + 1 < width; i += 2) {
77 EXPAND_UV(*lineU, *lineV);
78 lineU += uvPixelStride;
79 lineV += uvPixelStride;
80
81 rgb[i] = qYUVToARGB32(*lineY0++, rv, guv, bu);
82 rgb[i+1] = qYUVToARGB32(*lineY0++, rv, guv, bu);
83 }
84
85 y += yStride; // stride * 2
86 u += uStride;
87 v += vStride;
88 rgb += width;
89 }
90}
91
92static void QT_FASTCALL qt_convert_YUV420P_to_ARGB32(const QVideoFrame &frame, uchar *output)
93{
95 planarYUV420_to_ARGB32(plane1, plane1Stride,
96 plane2, plane2Stride,
97 plane3, plane3Stride,
98 1,
99 reinterpret_cast<quint32*>(output),
100 width, height);
101}
102
103static void QT_FASTCALL qt_convert_YUV422P_to_ARGB32(const QVideoFrame &frame, uchar *output)
104{
106 planarYUV422_to_ARGB32(plane1, plane1Stride,
107 plane2, plane2Stride,
108 plane3, plane3Stride,
109 1,
110 reinterpret_cast<quint32*>(output),
111 width, height);
112}
113
114
115static void QT_FASTCALL qt_convert_YV12_to_ARGB32(const QVideoFrame &frame, uchar *output)
116{
118 planarYUV420_to_ARGB32(plane1, plane1Stride,
119 plane3, plane3Stride,
120 plane2, plane2Stride,
121 1,
122 reinterpret_cast<quint32*>(output),
123 width, height);
124}
125
126static void QT_FASTCALL qt_convert_AYUV_to_ARGB32(const QVideoFrame &frame, uchar *output)
127{
128 FETCH_INFO_PACKED(frame)
129 MERGE_LOOPS(width, height, stride, 4)
130
131 quint32 *rgb = reinterpret_cast<quint32*>(output);
132
133 for (int i = 0; i < height; ++i) {
134 const uchar *lineSrc = src;
135
136 for (int j = 0; j < width; ++j) {
137 int a = *lineSrc++;
138 int y = *lineSrc++;
139 int u = *lineSrc++;
140 int v = *lineSrc++;
141
142 EXPAND_UV(u, v);
143
144 *rgb++ = qPremultiply(qYUVToARGB32(y, rv, guv, bu, a));
145 }
146
147 src += stride;
148 }
149}
150
151static void QT_FASTCALL qt_convert_AYUV_Premultiplied_to_ARGB32(const QVideoFrame &frame, uchar *output)
152{
153 FETCH_INFO_PACKED(frame)
154 MERGE_LOOPS(width, height, stride, 4)
155
156 quint32 *rgb = reinterpret_cast<quint32*>(output);
157
158 for (int i = 0; i < height; ++i) {
159 const uchar *lineSrc = src;
160
161 for (int j = 0; j < width; ++j) {
162 int a = *lineSrc++;
163 int y = *lineSrc++;
164 int u = *lineSrc++;
165 int v = *lineSrc++;
166
167 EXPAND_UV(u, v);
168
169 *rgb++ = qYUVToARGB32(y, rv, guv, bu, a);
170 }
171
172 src += stride;
173 }
174}
175
176static void QT_FASTCALL qt_convert_UYVY_to_ARGB32(const QVideoFrame &frame, uchar *output)
177{
178 FETCH_INFO_PACKED(frame)
179 MERGE_LOOPS(width, height, stride, 2)
180
181 quint32 *rgb = reinterpret_cast<quint32*>(output);
182
183 for (int i = 0; i < height; ++i) {
184 const uchar *lineSrc = src;
185 for (int j = 0; j + 1 < width; j += 2) {
186 int u = *lineSrc++;
187 int y0 = *lineSrc++;
188 int v = *lineSrc++;
189 int y1 = *lineSrc++;
190
191 EXPAND_UV(u, v);
192
193 rgb[j] = qYUVToARGB32(y0, rv, guv, bu);
194 rgb[j+1] = qYUVToARGB32(y1, rv, guv, bu);
195 }
196
197 src += stride;
198 rgb += width;
199 }
200}
201
202static void QT_FASTCALL qt_convert_YUYV_to_ARGB32(const QVideoFrame &frame, uchar *output)
203{
204 FETCH_INFO_PACKED(frame)
205 MERGE_LOOPS(width, height, stride, 2)
206
207 quint32 *rgb = reinterpret_cast<quint32*>(output);
208
209 for (int i = 0; i < height; ++i) {
210 const uchar *lineSrc = src;
211 for (int j = 0; j + 1 < width; j += 2) {
212 int y0 = *lineSrc++;
213 int u = *lineSrc++;
214 int y1 = *lineSrc++;
215 int v = *lineSrc++;
216
217 EXPAND_UV(u, v);
218
219 rgb[j] = qYUVToARGB32(y0, rv, guv, bu);
220 rgb[j+1] = qYUVToARGB32(y1, rv, guv, bu);
221 }
222
223 src += stride;
224 rgb += width;
225 }
226}
227
228static void QT_FASTCALL qt_convert_NV12_to_ARGB32(const QVideoFrame &frame, uchar *output)
229{
231 planarYUV420_to_ARGB32(plane1, plane1Stride,
232 plane2, plane2Stride,
233 plane2 + 1, plane2Stride,
234 2,
235 reinterpret_cast<quint32*>(output),
236 width, height);
237}
238
239static void QT_FASTCALL qt_convert_NV21_to_ARGB32(const QVideoFrame &frame, uchar *output)
240{
242 planarYUV420_to_ARGB32(plane1, plane1Stride,
243 plane2 + 1, plane2Stride,
244 plane2, plane2Stride,
245 2,
246 reinterpret_cast<quint32*>(output),
247 width, height);
248}
249
250static void QT_FASTCALL qt_convert_IMC1_to_ARGB32(const QVideoFrame &frame, uchar *output)
251{
253 Q_ASSERT(plane1Stride == plane2Stride);
254 Q_ASSERT(plane1Stride == plane3Stride);
255
256 planarYUV420_to_ARGB32(plane1, plane1Stride,
257 plane3, plane3Stride,
258 plane2, plane2Stride,
259 1,
260 reinterpret_cast<quint32*>(output),
261 width, height);
262}
263
264static void QT_FASTCALL qt_convert_IMC2_to_ARGB32(const QVideoFrame &frame, uchar *output)
265{
267 Q_ASSERT(plane1Stride == plane2Stride);
268
269 planarYUV420_to_ARGB32(plane1, plane1Stride,
270 plane2 + (plane1Stride >> 1), plane1Stride,
271 plane2, plane1Stride,
272 1,
273 reinterpret_cast<quint32*>(output),
274 width, height);
275}
276
277static void QT_FASTCALL qt_convert_IMC3_to_ARGB32(const QVideoFrame &frame, uchar *output)
278{
280 Q_ASSERT(plane1Stride == plane2Stride);
281 Q_ASSERT(plane1Stride == plane3Stride);
282
283 planarYUV420_to_ARGB32(plane1, plane1Stride,
284 plane2, plane2Stride,
285 plane3, plane3Stride,
286 1,
287 reinterpret_cast<quint32*>(output),
288 width, height);
289}
290
291static void QT_FASTCALL qt_convert_IMC4_to_ARGB32(const QVideoFrame &frame, uchar *output)
292{
294 Q_ASSERT(plane1Stride == plane2Stride);
295
296 planarYUV420_to_ARGB32(plane1, plane1Stride,
297 plane2, plane1Stride,
298 plane2 + (plane1Stride >> 1), plane1Stride,
299 1,
300 reinterpret_cast<quint32*>(output),
301 width, height);
302}
303
304
305template<typename Pixel>
306static void QT_FASTCALL qt_convert_to_ARGB32(const QVideoFrame &frame, uchar *output)
307{
308 FETCH_INFO_PACKED(frame)
309 MERGE_LOOPS(width, height, stride, 4)
310
311 quint32 *argb = reinterpret_cast<quint32*>(output);
312
313 for (int y = 0; y < height; ++y) {
314 const Pixel *data = reinterpret_cast<const Pixel *>(src);
315
316 int x = 0;
317 for (; x < width - 3; x += 4) {
318 // Copy 4 pixels onto the stack in one go. This significantly increases performance
319 // in the case where the mapped memory is uncached (because it's a framebuffer)
320 Pixel p[4];
321 memcpy(p, data, 4*sizeof(Pixel));
322 *argb++ = qPremultiply(p[0].convert());
323 *argb++ = qPremultiply(p[1].convert());
324 *argb++ = qPremultiply(p[2].convert());
325 *argb++ = qPremultiply(p[3].convert());
326 data += 4;
327 }
328
329 // leftovers
330 for (; x < width; ++x) {
331 *argb++ = qPremultiply(data->convert());
332 ++data;
333 }
334
335 src += stride;
336 }
337}
338
339template<typename Pixel>
340static void QT_FASTCALL qt_convert_premultiplied_to_ARGB32(const QVideoFrame &frame, uchar *output)
341{
342 FETCH_INFO_PACKED(frame)
343 MERGE_LOOPS(width, height, stride, 4)
344
345 quint32 *argb = reinterpret_cast<quint32*>(output);
346
347 for (int y = 0; y < height; ++y) {
348 const Pixel *data = reinterpret_cast<const Pixel *>(src);
349
350 int x = 0;
351 for (; x < width - 3; x += 4) {
352 // Copy 4 pixels onto the stack in one go. This significantly increases performance
353 // in the case where the mapped memory is uncached (because it's a framebuffer)
354 Pixel p[4];
355 memcpy(p, data, 4*sizeof(Pixel));
356 *argb++ = p[0].convert();
357 *argb++ = p[1].convert();
358 *argb++ = p[2].convert();
359 *argb++ = p[3].convert();
360 data += 4;
361 }
362
363 // leftovers
364 for (; x < width; ++x) {
365 *argb++ = data->convert();
366 ++data;
367 }
368
369 src += stride;
370 }
371}
372
373static inline void planarYUV420_16bit_to_ARGB32(const uchar *y, int yStride,
374 const uchar *u, int uStride,
375 const uchar *v, int vStride,
376 int uvPixelStride,
377 quint32 *rgb,
378 int width, int height)
379{
380 height &= ~1;
381
382 for (int j = 0; j + 1 < height; j += 2) {
383 const uchar *lineY0 = y;
384 const uchar *lineY1 = y + yStride;
385 const uchar *lineU = u;
386 const uchar *lineV = v;
387
388 quint32 *rgb0 = rgb;
389 quint32 *rgb1 = rgb + width;
390
391 for (int i = 0; i + 1 < width; i += 2) {
392 EXPAND_UV(*lineU, *lineV);
393 lineU += uvPixelStride;
394 lineV += uvPixelStride;
395
396 *rgb0++ = qYUVToARGB32(*lineY0, rv, guv, bu);
397 lineY0 += 2;
398 *rgb0++ = qYUVToARGB32(*lineY0, rv, guv, bu);
399 lineY0 += 2;
400 *rgb1++ = qYUVToARGB32(*lineY1, rv, guv, bu);
401 lineY1 += 2;
402 *rgb1++ = qYUVToARGB32(*lineY1, rv, guv, bu);
403 lineY1 += 2;
404 }
405
406 y += yStride << 1; // stride * 2
407 u += uStride;
408 v += vStride;
409 rgb += width * 2;
410 }
411}
412
413
414static void QT_FASTCALL qt_convert_P016_to_ARGB32(const QVideoFrame &frame, uchar *output)
415{
417 planarYUV420_16bit_to_ARGB32(plane1 + 1, plane1Stride,
418 plane2 + 1, plane2Stride,
419 plane2 + 3, plane2Stride,
420 4,
421 reinterpret_cast<quint32*>(output),
422 width, height);
423
424}
425
426template <typename Y>
427static void QT_FASTCALL qt_convert_Y_to_ARGB32(const QVideoFrame &frame, uchar *output)
428{
429 FETCH_INFO_PACKED(frame)
430 MERGE_LOOPS(width, height, stride, (int)sizeof(Y))
431 quint32 *argb = reinterpret_cast<quint32*>(output);
432
433 using Pixel = YPixel<Y>;
434
435 for (int y = 0; y < height; ++y) {
436 const Pixel *pixel = reinterpret_cast<const Pixel *>(src);
437
438 int x = 0;
439 for (; x < width - 3; x += 4) {
440 *argb++ = pixel->convert();
441 ++pixel;
442 *argb++ = pixel->convert();
443 ++pixel;
444 *argb++ = pixel->convert();
445 ++pixel;
446 *argb++ = pixel->convert();
447 ++pixel;
448 }
449
450 // leftovers
451 for (; x < width; ++x) {
452 *argb++ = pixel->convert();
453 ++pixel;
454 }
455
456 src += stride;
457 }
458 MERGE_LOOPS(width, height, stride, 1)
459}
460
461template<typename Pixel>
462static void QT_FASTCALL qt_copy_pixels_with_mask(Pixel *dst, const Pixel *src, size_t size,
463 Pixel mask)
464{
465 for (size_t x = 0; x < size; ++x)
466 dst[x] = src[x] | mask;
467}
468
469static VideoFrameConvertFunc qConvertFuncs[QVideoFrameFormat::NPixelFormats] = {
470 /* Format_Invalid */ nullptr, // Not needed
471 /* Format_ARGB8888 */ qt_convert_to_ARGB32<ARGB8888>,
472 /* Format_ARGB8888_Premultiplied */ qt_convert_premultiplied_to_ARGB32<ARGB8888>,
473 /* Format_XRGB8888 */ qt_convert_premultiplied_to_ARGB32<XRGB8888>,
474 /* Format_BGRA8888 */ qt_convert_to_ARGB32<BGRA8888>,
475 /* Format_BGRA8888_Premultiplied */ qt_convert_premultiplied_to_ARGB32<BGRA8888>,
476 /* Format_BGRX8888 */ qt_convert_premultiplied_to_ARGB32<BGRX8888>,
477 /* Format_ABGR8888 */ qt_convert_to_ARGB32<ABGR8888>,
478 /* Format_XBGR8888 */ qt_convert_premultiplied_to_ARGB32<XBGR8888>,
479 /* Format_RGBA8888 */ qt_convert_to_ARGB32<RGBA8888>,
480 /* Format_RGBX8888 */ qt_convert_premultiplied_to_ARGB32<RGBX8888>,
481 /* Format_AYUV */ qt_convert_AYUV_to_ARGB32,
482 /* Format_AYUV_Premultiplied */ qt_convert_AYUV_Premultiplied_to_ARGB32,
483 /* Format_YUV420P */ qt_convert_YUV420P_to_ARGB32,
484 /* Format_YUV422P */ qt_convert_YUV422P_to_ARGB32,
485 /* Format_YV12 */ qt_convert_YV12_to_ARGB32,
486 /* Format_UYVY */ qt_convert_UYVY_to_ARGB32,
487 /* Format_YUYV */ qt_convert_YUYV_to_ARGB32,
488 /* Format_NV12 */ qt_convert_NV12_to_ARGB32,
489 /* Format_NV21 */ qt_convert_NV21_to_ARGB32,
490 /* Format_IMC1 */ qt_convert_IMC1_to_ARGB32,
491 /* Format_IMC2 */ qt_convert_IMC2_to_ARGB32,
492 /* Format_IMC3 */ qt_convert_IMC3_to_ARGB32,
493 /* Format_IMC4 */ qt_convert_IMC4_to_ARGB32,
494 /* Format_Y8 */ qt_convert_Y_to_ARGB32<uchar>,
495 /* Format_Y16 */ qt_convert_Y_to_ARGB32<ushort>,
496 /* Format_P010 */ qt_convert_P016_to_ARGB32,
497 /* Format_P016 */ qt_convert_P016_to_ARGB32,
498 /* Format_Jpeg */ nullptr, // Not needed
499};
500
501static PixelsCopyFunc qPixelsCopyFunc = qt_copy_pixels_with_mask<uint32_t>;
502
503static std::once_flag InitFuncsAsmFlag;
504
505static void qInitFuncsAsm()
506{
507#ifdef QT_COMPILER_SUPPORTS_SSE2
508 extern void QT_FASTCALL qt_convert_ARGB8888_to_ARGB32_sse2(const QVideoFrame &frame, uchar *output);
509 extern void QT_FASTCALL qt_convert_ABGR8888_to_ARGB32_sse2(const QVideoFrame &frame, uchar *output);
510 extern void QT_FASTCALL qt_convert_RGBA8888_to_ARGB32_sse2(const QVideoFrame &frame, uchar *output);
511 extern void QT_FASTCALL qt_convert_BGRA8888_to_ARGB32_sse2(const QVideoFrame &frame, uchar *output);
512 extern void QT_FASTCALL qt_copy_pixels_with_mask_sse2(uint32_t * dst, const uint32_t *src, size_t size, uint32_t mask);
513
514 if (qCpuHasFeature(SSE2)){
515 qConvertFuncs[QVideoFrameFormat::Format_ARGB8888] = qt_convert_ARGB8888_to_ARGB32_sse2;
516 qConvertFuncs[QVideoFrameFormat::Format_ARGB8888_Premultiplied] = qt_convert_ARGB8888_to_ARGB32_sse2;
517 qConvertFuncs[QVideoFrameFormat::Format_XRGB8888] = qt_convert_ARGB8888_to_ARGB32_sse2;
518 qConvertFuncs[QVideoFrameFormat::Format_BGRA8888] = qt_convert_BGRA8888_to_ARGB32_sse2;
519 qConvertFuncs[QVideoFrameFormat::Format_BGRA8888_Premultiplied] = qt_convert_BGRA8888_to_ARGB32_sse2;
520 qConvertFuncs[QVideoFrameFormat::Format_BGRX8888] = qt_convert_BGRA8888_to_ARGB32_sse2;
521 qConvertFuncs[QVideoFrameFormat::Format_ABGR8888] = qt_convert_ABGR8888_to_ARGB32_sse2;
522 qConvertFuncs[QVideoFrameFormat::Format_XBGR8888] = qt_convert_ABGR8888_to_ARGB32_sse2;
523 qConvertFuncs[QVideoFrameFormat::Format_RGBA8888] = qt_convert_RGBA8888_to_ARGB32_sse2;
524 qConvertFuncs[QVideoFrameFormat::Format_RGBX8888] = qt_convert_RGBA8888_to_ARGB32_sse2;
525
526 qPixelsCopyFunc = qt_copy_pixels_with_mask_sse2;
527 }
528#endif
529#ifdef QT_COMPILER_SUPPORTS_SSSE3
530 extern void QT_FASTCALL qt_convert_ARGB8888_to_ARGB32_ssse3(const QVideoFrame &frame, uchar *output);
531 extern void QT_FASTCALL qt_convert_ABGR8888_to_ARGB32_ssse3(const QVideoFrame &frame, uchar *output);
532 extern void QT_FASTCALL qt_convert_RGBA8888_to_ARGB32_ssse3(const QVideoFrame &frame, uchar *output);
533 extern void QT_FASTCALL qt_convert_BGRA8888_to_ARGB32_ssse3(const QVideoFrame &frame, uchar *output);
534 if (qCpuHasFeature(SSSE3)){
535 qConvertFuncs[QVideoFrameFormat::Format_ARGB8888] = qt_convert_ARGB8888_to_ARGB32_ssse3;
536 qConvertFuncs[QVideoFrameFormat::Format_ARGB8888_Premultiplied] = qt_convert_ARGB8888_to_ARGB32_ssse3;
537 qConvertFuncs[QVideoFrameFormat::Format_XRGB8888] = qt_convert_ARGB8888_to_ARGB32_ssse3;
538 qConvertFuncs[QVideoFrameFormat::Format_BGRA8888] = qt_convert_BGRA8888_to_ARGB32_ssse3;
539 qConvertFuncs[QVideoFrameFormat::Format_BGRA8888_Premultiplied] = qt_convert_BGRA8888_to_ARGB32_ssse3;
540 qConvertFuncs[QVideoFrameFormat::Format_BGRX8888] = qt_convert_BGRA8888_to_ARGB32_ssse3;
541 qConvertFuncs[QVideoFrameFormat::Format_ABGR8888] = qt_convert_ABGR8888_to_ARGB32_ssse3;
542 qConvertFuncs[QVideoFrameFormat::Format_XBGR8888] = qt_convert_ABGR8888_to_ARGB32_ssse3;
543 qConvertFuncs[QVideoFrameFormat::Format_RGBA8888] = qt_convert_RGBA8888_to_ARGB32_ssse3;
544 qConvertFuncs[QVideoFrameFormat::Format_RGBX8888] = qt_convert_RGBA8888_to_ARGB32_ssse3;
545 }
546#endif
547#ifdef QT_COMPILER_SUPPORTS_AVX2
548 extern void QT_FASTCALL qt_convert_ARGB8888_to_ARGB32_avx2(const QVideoFrame &frame, uchar *output);
549 extern void QT_FASTCALL qt_convert_ABGR8888_to_ARGB32_avx2(const QVideoFrame &frame, uchar *output);
550 extern void QT_FASTCALL qt_convert_RGBA8888_to_ARGB32_avx2(const QVideoFrame &frame, uchar *output);
551 extern void QT_FASTCALL qt_convert_BGRA8888_to_ARGB32_avx2(const QVideoFrame &frame, uchar *output);
552 extern void QT_FASTCALL qt_copy_pixels_with_mask_avx2(uint32_t * dst, const uint32_t *src, size_t size, uint32_t mask);
553 if (qCpuHasFeature(AVX2)){
554 qConvertFuncs[QVideoFrameFormat::Format_ARGB8888] = qt_convert_ARGB8888_to_ARGB32_avx2;
555 qConvertFuncs[QVideoFrameFormat::Format_ARGB8888_Premultiplied] = qt_convert_ARGB8888_to_ARGB32_avx2;
556 qConvertFuncs[QVideoFrameFormat::Format_XRGB8888] = qt_convert_ARGB8888_to_ARGB32_avx2;
557 qConvertFuncs[QVideoFrameFormat::Format_BGRA8888] = qt_convert_BGRA8888_to_ARGB32_avx2;
558 qConvertFuncs[QVideoFrameFormat::Format_BGRA8888_Premultiplied] = qt_convert_BGRA8888_to_ARGB32_avx2;
559 qConvertFuncs[QVideoFrameFormat::Format_BGRX8888] = qt_convert_BGRA8888_to_ARGB32_avx2;
560 qConvertFuncs[QVideoFrameFormat::Format_ABGR8888] = qt_convert_ABGR8888_to_ARGB32_avx2;
561 qConvertFuncs[QVideoFrameFormat::Format_XBGR8888] = qt_convert_ABGR8888_to_ARGB32_avx2;
562 qConvertFuncs[QVideoFrameFormat::Format_RGBA8888] = qt_convert_RGBA8888_to_ARGB32_avx2;
563 qConvertFuncs[QVideoFrameFormat::Format_RGBX8888] = qt_convert_RGBA8888_to_ARGB32_avx2;
564
565 qPixelsCopyFunc = qt_copy_pixels_with_mask_avx2;
566 }
567#endif
568}
569
570VideoFrameConvertFunc qConverterForFormat(QVideoFrameFormat::PixelFormat format)
571{
572 std::call_once(InitFuncsAsmFlag, &qInitFuncsAsm);
573
574 VideoFrameConvertFunc convert = qConvertFuncs[format];
575 return convert;
576}
577
578void Q_MULTIMEDIA_EXPORT qCopyPixelsWithAlphaMask(uint32_t *dst,
579 const uint32_t *src,
580 size_t pixCount,
581 QVideoFrameFormat::PixelFormat format,
582 bool srcAlphaVaries)
583{
584 if (pixCount == 0)
585 return;
586
587 const auto mask = qAlphaMask(format);
588
589 if (srcAlphaVaries || (src[0] & mask) != mask)
590 qCopyPixelsWithMask(dst, src, pixCount, mask);
591 else
592 memcpy(dst, src, pixCount * 4);
593}
594
595void qCopyPixelsWithMask(uint32_t *dst, const uint32_t *src, size_t size, uint32_t mask)
596{
597 std::call_once(InitFuncsAsmFlag, &qInitFuncsAsm);
598
599 qPixelsCopyFunc(dst, src, size, mask);
600}
601
602uint32_t qAlphaMask(QVideoFrameFormat::PixelFormat format)
603{
604 switch (format) {
605 case QVideoFrameFormat::Format_ARGB8888:
606 case QVideoFrameFormat::Format_ARGB8888_Premultiplied:
607 case QVideoFrameFormat::Format_XRGB8888:
608 case QVideoFrameFormat::Format_ABGR8888:
609 case QVideoFrameFormat::Format_XBGR8888:
610#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
611 return 0xff;
612#else
613 return 0xff000000;
614#endif
615 case QVideoFrameFormat::Format_BGRA8888:
616 case QVideoFrameFormat::Format_BGRA8888_Premultiplied:
617 case QVideoFrameFormat::Format_BGRX8888:
618 case QVideoFrameFormat::Format_RGBA8888:
619 case QVideoFrameFormat::Format_RGBX8888:
620#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
621 return 0xff000000;
622#else
623 return 0xff;
624#endif
625 default:
626 return 0;
627 }
628}
629
630QT_END_NAMESPACE
uint QT_FASTCALL fetch1Pixel< QPixelLayout::BPP1LSB >(const uchar *src, int index)
VideoFrameConvertFunc qConverterForFormat(QVideoFrameFormat::PixelFormat format)
#define EXPAND_UV(u, v)
uint32_t qAlphaMask(QVideoFrameFormat::PixelFormat format)
static void planarYUV420_to_ARGB32(const uchar *y, int yStride, const uchar *u, int uStride, const uchar *v, int vStride, int uvPixelStride, quint32 *rgb, int width, int height)
static void planarYUV420_16bit_to_ARGB32(const uchar *y, int yStride, const uchar *u, int uStride, const uchar *v, int vStride, int uvPixelStride, quint32 *rgb, int width, int height)
static VideoFrameConvertFunc qConvertFuncs[QVideoFrameFormat::NPixelFormats]
static PixelsCopyFunc qPixelsCopyFunc
void qCopyPixelsWithMask(uint32_t *dst, const uint32_t *src, size_t size, uint32_t mask)
static std::once_flag InitFuncsAsmFlag
static void planarYUV422_to_ARGB32(const uchar *y, int yStride, const uchar *u, int uStride, const uchar *v, int vStride, int uvPixelStride, quint32 *rgb, int width, int height)
static void qInitFuncsAsm()
#define CLAMP(n)
#define MERGE_LOOPS(width, height, stride, bpp)
#define FETCH_INFO_PACKED(frame)
#define FETCH_INFO_BIPLANAR(frame)
#define FETCH_INFO_TRIPLANAR(frame)