24 #include <winpr/wtypes.h>
26 #include <freerdp/config.h>
28 #include <freerdp/types.h>
29 #include <freerdp/primitives.h>
30 #include <freerdp/codec/color.h>
31 #include "prim_internal.h"
34 static pstatus_t general_LumaToYUV444(
const BYTE* WINPR_RESTRICT pSrcRaw[3],
35 const UINT32 srcStep[3], BYTE* WINPR_RESTRICT pDstRaw[3],
36 const UINT32 dstStep[3],
39 const UINT32 nWidth = roi->right - roi->left;
40 const UINT32 nHeight = roi->bottom - roi->top;
41 const UINT32 halfWidth = (nWidth + 1) / 2;
42 const UINT32 halfHeight = (nHeight + 1) / 2;
43 const UINT32 oddY = 1;
44 const UINT32 evenY = 0;
45 const UINT32 oddX = 1;
46 const UINT32 evenX = 0;
47 const BYTE* pSrc[3] = { pSrcRaw[0] + 1ULL * roi->top * srcStep[0] + roi->left,
48 pSrcRaw[1] + 1ULL * roi->top / 2 * srcStep[1] + roi->left / 2,
49 pSrcRaw[2] + 1ULL * roi->top / 2 * srcStep[2] + roi->left / 2 };
50 BYTE* pDst[3] = { pDstRaw[0] + 1ULL * roi->top * dstStep[0] + roi->left,
51 pDstRaw[1] + 1ULL * roi->top * dstStep[1] + roi->left,
52 pDstRaw[2] + 1ULL * roi->top * dstStep[2] + roi->left };
56 for (
size_t y = 0; y < nHeight; y++)
58 const BYTE* Ym = pSrc[0] + y * srcStep[0];
59 BYTE* pY = pDst[0] + dstStep[0] * y;
60 memcpy(pY, Ym, nWidth);
65 for (UINT32 y = 0; y < halfHeight; y++)
67 const UINT32 val2y = (2UL * y + evenY);
68 const UINT32 val2y1 = val2y + oddY;
69 const BYTE* Um = pSrc[1] + 1ULL * y * srcStep[1];
70 const BYTE* Vm = pSrc[2] + 1ULL * y * srcStep[2];
71 BYTE* pU = pDst[1] + 1ULL * dstStep[1] * val2y;
72 BYTE* pV = pDst[2] + 1ULL * dstStep[2] * val2y;
73 BYTE* pU1 = pDst[1] + 1ULL * dstStep[1] * val2y1;
74 BYTE* pV1 = pDst[2] + 1ULL * dstStep[2] * val2y1;
76 for (UINT32 x = 0; x < halfWidth; x++)
78 const UINT32 val2x = 2UL * x + evenX;
79 const UINT32 val2x1 = val2x + oddX;
91 return PRIMITIVES_SUCCESS;
94 static pstatus_t general_ChromaFilter(BYTE* WINPR_RESTRICT pDst[3],
const UINT32 dstStep[3],
97 const UINT32 oddY = 1;
98 const UINT32 evenY = 0;
99 const UINT32 nWidth = roi->right - roi->left;
100 const UINT32 nHeight = roi->bottom - roi->top;
101 const UINT32 halfHeight = (nHeight + 1) / 2;
102 const UINT32 halfWidth = (nWidth + 1) / 2;
105 for (UINT32 y = roi->top; y < halfHeight + roi->top; y++)
107 const UINT32 val2y = (y * 2 + evenY);
108 const UINT32 val2y1 = val2y + oddY;
109 BYTE* pU1 = pDst[1] + 1ULL * dstStep[1] * val2y1;
110 BYTE* pV1 = pDst[2] + 1ULL * dstStep[2] * val2y1;
111 BYTE* pU = pDst[1] + 1ULL * dstStep[1] * val2y;
112 BYTE* pV = pDst[2] + 1ULL * dstStep[2] * val2y;
114 if (val2y1 > nHeight)
117 for (UINT32 x = roi->left; x < halfWidth + roi->left; x++)
119 const UINT32 val2x = (x * 2);
120 const UINT32 val2x1 = val2x + 1;
121 const BYTE inU = pU[val2x];
122 const BYTE inV = pV[val2x];
123 const INT32 up = inU * 4;
124 const INT32 vp = inV * 4;
131 u2020 = up - pU[val2x1] - pU1[val2x] - pU1[val2x1];
132 v2020 = vp - pV[val2x1] - pV1[val2x] - pV1[val2x1];
134 pU[val2x] = CONDITIONAL_CLIP(u2020, inU);
135 pV[val2x] = CONDITIONAL_CLIP(v2020, inV);
139 return PRIMITIVES_SUCCESS;
142 static pstatus_t general_ChromaV1ToYUV444(
const BYTE* WINPR_RESTRICT pSrcRaw[3],
143 const UINT32 srcStep[3], BYTE* WINPR_RESTRICT pDstRaw[3],
144 const UINT32 dstStep[3],
147 const UINT32 mod = 16;
150 const UINT32 nWidth = roi->right - roi->left;
151 const UINT32 nHeight = roi->bottom - roi->top;
152 const UINT32 halfWidth = (nWidth) / 2;
153 const UINT32 halfHeight = (nHeight) / 2;
154 const UINT32 oddY = 1;
155 const UINT32 evenY = 0;
156 const UINT32 oddX = 1;
159 const UINT32 padHeigth = nHeight + 16 - nHeight % 16;
160 const BYTE* pSrc[3] = { pSrcRaw[0] + 1ULL * roi->top * srcStep[0] + roi->left,
161 pSrcRaw[1] + 1ULL * roi->top / 2 * srcStep[1] + roi->left / 2,
162 pSrcRaw[2] + 1ULL * roi->top / 2 * srcStep[2] + roi->left / 2 };
163 BYTE* pDst[3] = { pDstRaw[0] + 1ULL * roi->top * dstStep[0] + roi->left,
164 pDstRaw[1] + 1ULL * roi->top * dstStep[1] + roi->left,
165 pDstRaw[2] + 1ULL * roi->top * dstStep[2] + roi->left };
169 for (
size_t y = 0; y < padHeigth; y++)
171 const BYTE* Ya = pSrc[0] + y * srcStep[0];
174 if ((y) % mod < (mod + 1) / 2)
176 const size_t pos = (2 * uY++ + oddY);
181 pX = pDst[1] + dstStep[1] * pos;
185 const size_t pos = (2 * vY++ + oddY);
190 pX = pDst[2] + dstStep[2] * pos;
193 memcpy(pX, Ya, nWidth);
197 for (UINT32 y = 0; y < halfHeight; y++)
199 const UINT32 val2y = (y * 2UL + evenY);
200 const BYTE* Ua = pSrc[1] + 1ULL * y * srcStep[1];
201 const BYTE* Va = pSrc[2] + 1ULL * y * srcStep[2];
202 BYTE* pU = pDst[1] + 1ULL * dstStep[1] * val2y;
203 BYTE* pV = pDst[2] + 1ULL * dstStep[2] * val2y;
205 for (UINT32 x = 0; x < halfWidth; x++)
207 const UINT32 val2x1 = (x * 2 + oddX);
214 return general_ChromaFilter(pDst, dstStep, roi);
217 static pstatus_t general_ChromaV2ToYUV444(
const BYTE* WINPR_RESTRICT pSrc[3],
218 const UINT32 srcStep[3], UINT32 nTotalWidth,
219 UINT32 nTotalHeight, BYTE* WINPR_RESTRICT pDst[3],
220 const UINT32 dstStep[3],
223 const UINT32 nWidth = roi->right - roi->left;
224 const UINT32 nHeight = roi->bottom - roi->top;
225 const UINT32 halfWidth = (nWidth + 1) / 2;
226 const UINT32 halfHeight = (nHeight + 1) / 2;
227 const UINT32 quaterWidth = (nWidth + 3) / 4;
230 for (UINT32 y = 0; y < nHeight; y++)
232 const UINT32 yTop = y + roi->top;
233 const BYTE* pYaU = pSrc[0] + 1ULL * srcStep[0] * yTop + roi->left / 2;
234 const BYTE* pYaV = pYaU + nTotalWidth / 2;
235 BYTE* pU = pDst[1] + 1ULL * dstStep[1] * yTop + roi->left;
236 BYTE* pV = pDst[2] + 1ULL * dstStep[2] * yTop + roi->left;
238 for (UINT32 x = 0; x < halfWidth; x++)
240 const UINT32 odd = 2UL * x + 1UL;
247 for (
size_t y = 0; y < halfHeight; y++)
249 const BYTE* pUaU = pSrc[1] + srcStep[1] * (y + roi->top / 2) + roi->left / 4;
250 const BYTE* pUaV = pUaU + nTotalWidth / 4;
251 const BYTE* pVaU = pSrc[2] + srcStep[2] * (y + roi->top / 2) + roi->left / 4;
252 const BYTE* pVaV = pVaU + nTotalWidth / 4;
253 BYTE* pU = pDst[1] + 1ULL * dstStep[1] * (2ULL * y + 1 + roi->top) + roi->left;
254 BYTE* pV = pDst[2] + 1ULL * dstStep[2] * (2ULL * y + 1 + roi->top) + roi->left;
256 for (
size_t x = 0; x < quaterWidth; x++)
258 pU[4 * x + 0] = *pUaU++;
259 pV[4 * x + 0] = *pUaV++;
260 pU[4 * x + 2] = *pVaU++;
261 pV[4 * x + 2] = *pVaV++;
265 return general_ChromaFilter(pDst, dstStep, roi);
268 static pstatus_t general_YUV420CombineToYUV444(avc444_frame_type type,
269 const BYTE* WINPR_RESTRICT pSrc[3],
270 const UINT32 srcStep[3], UINT32 nWidth,
271 UINT32 nHeight, BYTE* WINPR_RESTRICT pDst[3],
272 const UINT32 dstStep[3],
275 if (!pSrc || !pSrc[0] || !pSrc[1] || !pSrc[2])
278 if (!pDst || !pDst[0] || !pDst[1] || !pDst[2])
287 return general_LumaToYUV444(pSrc, srcStep, pDst, dstStep, roi);
289 case AVC444_CHROMAv1:
290 return general_ChromaV1ToYUV444(pSrc, srcStep, pDst, dstStep, roi);
292 case AVC444_CHROMAv2:
293 return general_ChromaV2ToYUV444(pSrc, srcStep, nWidth, nHeight, pDst, dstStep, roi);
301 general_YUV444SplitToYUV420(
const BYTE* WINPR_RESTRICT pSrc[3],
const UINT32 srcStep[3],
302 BYTE* WINPR_RESTRICT pMainDst[3],
const UINT32 dstMainStep[3],
303 BYTE* WINPR_RESTRICT pAuxDst[3],
const UINT32 dstAuxStep[3],
308 UINT32 halfWidth = 0;
309 UINT32 halfHeight = 0;
312 const UINT32 padHeigth = roi->height + 16 - roi->height % 16;
313 halfWidth = (roi->width + 1) / 2;
314 halfHeight = (roi->height + 1) / 2;
317 for (
size_t y = 0; y < roi->height; y++)
319 const BYTE* pSrcY = pSrc[0] + y * srcStep[0];
320 BYTE* pY = pMainDst[0] + y * dstMainStep[0];
321 memcpy(pY, pSrcY, roi->width);
325 for (
size_t y = 0; y < halfHeight; y++)
327 const BYTE* pSrcU = pSrc[1] + 2ULL * y * srcStep[1];
328 const BYTE* pSrcV = pSrc[2] + 2ULL * y * srcStep[2];
329 const BYTE* pSrcU1 = pSrc[1] + (2ULL * y + 1ULL) * srcStep[1];
330 const BYTE* pSrcV1 = pSrc[2] + (2ULL * y + 1ULL) * srcStep[2];
331 BYTE* pU = pMainDst[1] + y * dstMainStep[1];
332 BYTE* pV = pMainDst[2] + y * dstMainStep[2];
334 for (
size_t x = 0; x < halfWidth; x++)
337 const INT32 u = pSrcU[2 * x] + pSrcU[2 * x + 1] + pSrcU1[2 * x] + pSrcU1[2 * x + 1];
338 const INT32 v = pSrcV[2 * x] + pSrcV[2 * x + 1] + pSrcV1[2 * x] + pSrcV1[2 * x + 1];
339 pU[x] = CLIP(u / 4L);
340 pV[x] = CLIP(v / 4L);
345 for (
size_t y = 0; y < padHeigth; y++)
347 BYTE* pY = pAuxDst[0] + y * dstAuxStep[0];
351 const size_t pos = (2 * uY++ + 1);
352 const BYTE* pSrcU = pSrc[1] + pos * srcStep[1];
354 if (pos >= roi->height)
357 memcpy(pY, pSrcU, roi->width);
361 const size_t pos = (2 * vY++ + 1);
362 const BYTE* pSrcV = pSrc[2] + pos * srcStep[2];
364 if (pos >= roi->height)
367 memcpy(pY, pSrcV, roi->width);
372 for (
size_t y = 0; y < halfHeight; y++)
374 const BYTE* pSrcU = pSrc[1] + 2 * y * srcStep[1];
375 const BYTE* pSrcV = pSrc[2] + 2 * y * srcStep[2];
376 BYTE* pU = pAuxDst[1] + y * dstAuxStep[1];
377 BYTE* pV = pAuxDst[2] + y * dstAuxStep[2];
379 for (
size_t x = 0; x < halfWidth; x++)
381 pU[x] = pSrcU[2 * x + 1];
382 pV[x] = pSrcV[2 * x + 1];
386 return PRIMITIVES_SUCCESS;
389 static pstatus_t general_YUV444ToRGB_8u_P3AC4R_general(
const BYTE* WINPR_RESTRICT pSrc[3],
390 const UINT32 srcStep[3],
391 BYTE* WINPR_RESTRICT pDst, UINT32 dstStep,
395 const DWORD formatSize = FreeRDPGetBytesPerPixel(DstFormat);
396 fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, FALSE);
402 const UINT32 nWidth = roi->width;
403 const UINT32 nHeight = roi->height;
405 for (
size_t y = 0; y < nHeight; y++)
407 const BYTE* pY = pSrc[0] + y * srcStep[0];
408 const BYTE* pU = pSrc[1] + y * srcStep[1];
409 const BYTE* pV = pSrc[2] + y * srcStep[2];
410 BYTE* pRGB = pDst + y * dstStep;
412 for (
size_t x = 0; x < nWidth; x++)
414 const BYTE Y = pY[x];
415 const BYTE U = pU[x];
416 const BYTE V = pV[x];
417 const BYTE r = YUV2R(Y, U, V);
418 const BYTE g = YUV2G(Y, U, V);
419 const BYTE b = YUV2B(Y, U, V);
420 pRGB = writePixel(pRGB, formatSize, DstFormat, r, g, b, 0);
424 return PRIMITIVES_SUCCESS;
427 static pstatus_t general_YUV444ToRGB_8u_P3AC4R_BGRX(
const BYTE* WINPR_RESTRICT pSrc[3],
428 const UINT32 srcStep[3],
429 BYTE* WINPR_RESTRICT pDst, UINT32 dstStep,
433 const DWORD formatSize = FreeRDPGetBytesPerPixel(DstFormat);
439 const UINT32 nWidth = roi->width;
440 const UINT32 nHeight = roi->height;
442 for (
size_t y = 0; y < nHeight; y++)
444 const BYTE* pY = pSrc[0] + y * srcStep[0];
445 const BYTE* pU = pSrc[1] + y * srcStep[1];
446 const BYTE* pV = pSrc[2] + y * srcStep[2];
447 BYTE* pRGB = pDst + y * dstStep;
449 for (
size_t x = 0; x < nWidth; x++)
451 const BYTE Y = pY[x];
452 const BYTE U = pU[x];
453 const BYTE V = pV[x];
454 const BYTE r = YUV2R(Y, U, V);
455 const BYTE g = YUV2G(Y, U, V);
456 const BYTE b = YUV2B(Y, U, V);
457 pRGB = writePixelBGRX(pRGB, formatSize, DstFormat, r, g, b, 0);
461 return PRIMITIVES_SUCCESS;
464 static pstatus_t general_YUV444ToRGB_8u_P3AC4R(
const BYTE* WINPR_RESTRICT pSrc[3],
465 const UINT32 srcStep[3], BYTE* WINPR_RESTRICT pDst,
466 UINT32 dstStep, UINT32 DstFormat,
471 case PIXEL_FORMAT_BGRA32:
472 case PIXEL_FORMAT_BGRX32:
473 return general_YUV444ToRGB_8u_P3AC4R_BGRX(pSrc, srcStep, pDst, dstStep, DstFormat, roi);
476 return general_YUV444ToRGB_8u_P3AC4R_general(pSrc, srcStep, pDst, dstStep, DstFormat,
485 static pstatus_t general_YUV420ToRGB_8u_P3AC4R(
const BYTE* WINPR_RESTRICT pSrc[3],
486 const UINT32 srcStep[3], BYTE* WINPR_RESTRICT pDst,
487 UINT32 dstStep, UINT32 DstFormat,
495 UINT32 halfWidth = 0;
496 UINT32 halfHeight = 0;
497 const BYTE* pY = NULL;
498 const BYTE* pU = NULL;
499 const BYTE* pV = NULL;
505 const DWORD formatSize = FreeRDPGetBytesPerPixel(DstFormat);
506 fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, FALSE);
510 lastCol = roi->width & 0x01;
511 lastRow = roi->height & 0x01;
512 nWidth = (roi->width + 1) & ~0x0001;
513 nHeight = (roi->height + 1) & ~0x0001;
514 halfWidth = nWidth / 2;
515 halfHeight = nHeight / 2;
516 srcPad[0] = (srcStep[0] - nWidth);
517 srcPad[1] = (srcStep[1] - halfWidth);
518 srcPad[2] = (srcStep[2] - halfWidth);
519 dstPad = (dstStep - (nWidth * 4));
521 for (UINT32 y = 0; y < halfHeight;)
523 if (++y == halfHeight)
526 for (UINT32 x = 0; x < halfWidth;)
532 if (++x == halfWidth)
542 pRGB = writePixel(pRGB, formatSize, DstFormat, r, g, b, 0);
545 if (!(lastCol & 0x02))
551 pRGB = writePixel(pRGB, formatSize, DstFormat, r, g, b, 0);
569 for (UINT32 x = 0; x < halfWidth;)
575 if (++x == halfWidth)
585 pRGB = writePixel(pRGB, formatSize, DstFormat, r, g, b, 0);
588 if (!(lastCol & 0x02))
594 pRGB = writePixel(pRGB, formatSize, DstFormat, r, g, b, 0);
610 return PRIMITIVES_SUCCESS;
618 static INLINE BYTE RGB2Y(BYTE R, BYTE G, BYTE B)
620 return (54 * R + 183 * G + 18 * B) >> 8;
623 static INLINE BYTE RGB2U(BYTE R, BYTE G, BYTE B)
625 return ((-29 * R - 99 * G + 128 * B) >> 8) + 128;
628 static INLINE BYTE RGB2V(INT32 R, INT32 G, INT32 B)
630 return ((128 * R - 116 * G - 12 * B) >> 8) + 128;
634 static pstatus_t general_RGBToYUV444_8u_P3AC4R(
const BYTE* WINPR_RESTRICT pSrc, UINT32 SrcFormat,
635 const UINT32 srcStep, BYTE* WINPR_RESTRICT pDst[3],
640 const UINT32 bpp = FreeRDPGetBytesPerPixel(SrcFormat);
644 nHeight = roi->height;
646 for (
size_t y = 0; y < nHeight; y++)
648 const BYTE* pRGB = pSrc + y * srcStep;
649 BYTE* pY = pDst[0] + y * dstStep[0];
650 BYTE* pU = pDst[1] + y * dstStep[1];
651 BYTE* pV = pDst[2] + y * dstStep[2];
653 for (
size_t x = 0; x < nWidth; x++)
658 const UINT32 color = FreeRDPReadColor(&pRGB[x * bpp], SrcFormat);
659 FreeRDPSplitColor(color, SrcFormat, &R, &G, &B, NULL, NULL);
660 pY[x] = RGB2Y(R, G, B);
661 pU[x] = RGB2U(R, G, B);
662 pV[x] = RGB2V(R, G, B);
666 return PRIMITIVES_SUCCESS;
669 static INLINE pstatus_t general_RGBToYUV420_BGRX(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcStep,
670 BYTE* WINPR_RESTRICT pDst[3],
671 const UINT32 dstStep[3],
678 size_t x4 = srcStep + 4;
681 size_t y3 = dstStep[0];
682 size_t y4 = dstStep[0] + 1;
683 UINT32 max_x = roi->width - 1;
684 UINT32 max_y = roi->height - 1;
686 for (
size_t y = i = 0; y < roi->height; y += 2, i++)
688 const BYTE* src = pSrc + y * srcStep;
689 BYTE* ydst = pDst[0] + y * dstStep[0];
690 BYTE* udst = pDst[1] + i * dstStep[1];
691 BYTE* vdst = pDst[2] + i * dstStep[2];
693 for (
size_t x = 0; x < roi->width; x += 2)
702 Ba = B = *(src + x1 + 0);
703 Ga = G = *(src + x1 + 1);
704 Ra = R = *(src + x1 + 2);
705 ydst[y1] = RGB2Y(R, G, B);
710 Ba += B = *(src + x2 + 0);
711 Ga += G = *(src + x2 + 1);
712 Ra += R = *(src + x2 + 2);
713 ydst[y2] = RGB2Y(R, G, B);
719 Ba += B = *(src + x3 + 0);
720 Ga += G = *(src + x3 + 1);
721 Ra += R = *(src + x3 + 2);
722 ydst[y3] = RGB2Y(R, G, B);
727 Ba += B = *(src + x4 + 0);
728 Ga += G = *(src + x4 + 1);
729 Ra += R = *(src + x4 + 2);
730 ydst[y4] = RGB2Y(R, G, B);
737 *udst++ = RGB2U(Ra, Ga, Ba);
738 *vdst++ = RGB2V(Ra, Ga, Ba);
744 return PRIMITIVES_SUCCESS;
747 static INLINE pstatus_t general_RGBToYUV420_RGBX(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcStep,
748 BYTE* WINPR_RESTRICT pDst[3],
749 const UINT32 dstStep[3],
755 size_t x4 = srcStep + 4;
758 size_t y3 = dstStep[0];
759 size_t y4 = dstStep[0] + 1;
760 UINT32 max_x = roi->width - 1;
761 UINT32 max_y = roi->height - 1;
763 for (
size_t y = 0, i = 0; y < roi->height; y += 2, i++)
765 const BYTE* src = pSrc + y * srcStep;
766 BYTE* ydst = pDst[0] + y * dstStep[0];
767 BYTE* udst = pDst[1] + i * dstStep[1];
768 BYTE* vdst = pDst[2] + i * dstStep[2];
770 for (UINT32 x = 0; x < roi->width; x += 2)
779 Ra = R = *(src + x1 + 0);
780 Ga = G = *(src + x1 + 1);
781 Ba = B = *(src + x1 + 2);
782 ydst[y1] = RGB2Y(R, G, B);
787 Ra += R = *(src + x2 + 0);
788 Ga += G = *(src + x2 + 1);
789 Ba += B = *(src + x2 + 2);
790 ydst[y2] = RGB2Y(R, G, B);
796 Ra += R = *(src + x3 + 0);
797 Ga += G = *(src + x3 + 1);
798 Ba += B = *(src + x3 + 2);
799 ydst[y3] = RGB2Y(R, G, B);
804 Ra += R = *(src + x4 + 0);
805 Ga += G = *(src + x4 + 1);
806 Ba += B = *(src + x4 + 2);
807 ydst[y4] = RGB2Y(R, G, B);
814 *udst++ = RGB2U(Ra, Ga, Ba);
815 *vdst++ = RGB2V(Ra, Ga, Ba);
821 return PRIMITIVES_SUCCESS;
824 static INLINE pstatus_t general_RGBToYUV420_ANY(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcFormat,
825 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst[3],
826 const UINT32 dstStep[3],
829 const UINT32 bpp = FreeRDPGetBytesPerPixel(srcFormat);
833 size_t x4 = srcStep + bpp;
836 size_t y3 = dstStep[0];
837 size_t y4 = dstStep[0] + 1;
838 UINT32 max_x = roi->width - 1;
839 UINT32 max_y = roi->height - 1;
841 for (
size_t y = 0, i = 0; y < roi->height; y += 2, i++)
843 const BYTE* src = pSrc + y * srcStep;
844 BYTE* ydst = pDst[0] + y * dstStep[0];
845 BYTE* udst = pDst[1] + i * dstStep[1];
846 BYTE* vdst = pDst[2] + i * dstStep[2];
848 for (
size_t x = 0; x < roi->width; x += 2)
858 color = FreeRDPReadColor(src + x1, srcFormat);
859 FreeRDPSplitColor(color, srcFormat, &R, &G, &B, NULL, NULL);
863 ydst[y1] = RGB2Y(R, G, B);
868 color = FreeRDPReadColor(src + x2, srcFormat);
869 FreeRDPSplitColor(color, srcFormat, &R, &G, &B, NULL, NULL);
873 ydst[y2] = RGB2Y(R, G, B);
879 color = FreeRDPReadColor(src + x3, srcFormat);
880 FreeRDPSplitColor(color, srcFormat, &R, &G, &B, NULL, NULL);
884 ydst[y3] = RGB2Y(R, G, B);
889 color = FreeRDPReadColor(src + x4, srcFormat);
890 FreeRDPSplitColor(color, srcFormat, &R, &G, &B, NULL, NULL);
894 ydst[y4] = RGB2Y(R, G, B);
901 *udst++ = RGB2U(Ra, Ga, Ba);
902 *vdst++ = RGB2V(Ra, Ga, Ba);
908 return PRIMITIVES_SUCCESS;
911 static pstatus_t general_RGBToYUV420_8u_P3AC4R(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcFormat,
912 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst[3],
913 const UINT32 dstStep[3],
918 case PIXEL_FORMAT_BGRA32:
919 case PIXEL_FORMAT_BGRX32:
920 return general_RGBToYUV420_BGRX(pSrc, srcStep, pDst, dstStep, roi);
922 case PIXEL_FORMAT_RGBA32:
923 case PIXEL_FORMAT_RGBX32:
924 return general_RGBToYUV420_RGBX(pSrc, srcStep, pDst, dstStep, roi);
927 return general_RGBToYUV420_ANY(pSrc, srcFormat, srcStep, pDst, dstStep, roi);
931 static INLINE
void general_RGBToAVC444YUV_BGRX_DOUBLE_ROW(
932 const BYTE* WINPR_RESTRICT srcEven,
const BYTE* WINPR_RESTRICT srcOdd,
933 BYTE* WINPR_RESTRICT b1Even, BYTE* WINPR_RESTRICT b1Odd, BYTE* WINPR_RESTRICT b2,
934 BYTE* WINPR_RESTRICT b3, BYTE* WINPR_RESTRICT b4, BYTE* WINPR_RESTRICT b5,
935 BYTE* WINPR_RESTRICT b6, BYTE* WINPR_RESTRICT b7, UINT32 width)
937 for (UINT32 x = 0; x < width; x += 2)
939 const BOOL lastX = (x + 1) >= width;
954 const BYTE b = *srcEven++;
955 const BYTE g = *srcEven++;
956 const BYTE r = *srcEven++;
958 Y1e = Y2e = Y1o = Y2o = RGB2Y(r, g, b);
959 U1e = U2e = U1o = U2o = RGB2U(r, g, b);
960 V1e = V2e = V1o = V2o = RGB2V(r, g, b);
965 const BYTE b = *srcEven++;
966 const BYTE g = *srcEven++;
967 const BYTE r = *srcEven++;
969 Y2e = RGB2Y(r, g, b);
970 U2e = RGB2U(r, g, b);
971 V2e = RGB2V(r, g, b);
976 const BYTE b = *srcOdd++;
977 const BYTE g = *srcOdd++;
978 const BYTE r = *srcOdd++;
980 Y1o = Y2o = RGB2Y(r, g, b);
981 U1o = U2o = RGB2U(r, g, b);
982 V1o = V2o = RGB2V(r, g, b);
987 const BYTE b = *srcOdd++;
988 const BYTE g = *srcOdd++;
989 const BYTE r = *srcOdd++;
991 Y2o = RGB2Y(r, g, b);
992 U2o = RGB2U(r, g, b);
993 V2o = RGB2V(r, g, b);
1009 const BYTE Uavg = ((UINT16)U1e + (UINT16)U2e + (UINT16)U1o + (UINT16)U2o) / 4;
1010 const BYTE Vavg = ((UINT16)V1e + (UINT16)V2e + (UINT16)V1o + (UINT16)V2o) / 4;
1037 static INLINE pstatus_t general_RGBToAVC444YUV_BGRX(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcStep,
1038 BYTE* WINPR_RESTRICT pDst1[3],
1039 const UINT32 dst1Step[3],
1040 BYTE* WINPR_RESTRICT pDst2[3],
1041 const UINT32 dst2Step[3],
1048 const BYTE* pMaxSrc = pSrc + 1ULL * (roi->height - 1) * srcStep;
1050 for (UINT32 y = 0; y < roi->height; y += 2)
1052 const BOOL last = (y >= (roi->height - 1));
1053 const BYTE* srcEven = y < roi->height ? pSrc + 1ULL * y * srcStep : pMaxSrc;
1054 const BYTE* srcOdd = !last ? pSrc + 1ULL * (y + 1) * srcStep : pMaxSrc;
1055 const UINT32 i = y >> 1;
1056 const UINT32 n = (i & ~7) + i;
1057 BYTE* b1Even = pDst1[0] + 1ULL * y * dst1Step[0];
1058 BYTE* b1Odd = !last ? (b1Even + dst1Step[0]) : NULL;
1059 BYTE* b2 = pDst1[1] + 1ULL * (y / 2) * dst1Step[1];
1060 BYTE* b3 = pDst1[2] + 1ULL * (y / 2) * dst1Step[2];
1061 BYTE* b4 = pDst2[0] + 1ULL * dst2Step[0] * n;
1062 BYTE* b5 = b4 + 8ULL * dst2Step[0];
1063 BYTE* b6 = pDst2[1] + 1ULL * (y / 2) * dst2Step[1];
1064 BYTE* b7 = pDst2[2] + 1ULL * (y / 2) * dst2Step[2];
1065 general_RGBToAVC444YUV_BGRX_DOUBLE_ROW(srcEven, srcOdd, b1Even, b1Odd, b2, b3, b4, b5, b6,
1069 return PRIMITIVES_SUCCESS;
1072 static INLINE
void general_RGBToAVC444YUV_RGBX_DOUBLE_ROW(
1073 const BYTE* WINPR_RESTRICT srcEven,
const BYTE* WINPR_RESTRICT srcOdd,
1074 BYTE* WINPR_RESTRICT b1Even, BYTE* WINPR_RESTRICT b1Odd, BYTE* WINPR_RESTRICT b2,
1075 BYTE* WINPR_RESTRICT b3, BYTE* WINPR_RESTRICT b4, BYTE* WINPR_RESTRICT b5,
1076 BYTE* WINPR_RESTRICT b6, BYTE* WINPR_RESTRICT b7, UINT32 width)
1078 for (UINT32 x = 0; x < width; x += 2)
1080 const BOOL lastX = (x + 1) >= width;
1095 const BYTE r = *srcEven++;
1096 const BYTE g = *srcEven++;
1097 const BYTE b = *srcEven++;
1099 Y1e = Y2e = Y1o = Y2o = RGB2Y(r, g, b);
1100 U1e = U2e = U1o = U2o = RGB2U(r, g, b);
1101 V1e = V2e = V1o = V2o = RGB2V(r, g, b);
1106 const BYTE r = *srcEven++;
1107 const BYTE g = *srcEven++;
1108 const BYTE b = *srcEven++;
1110 Y2e = RGB2Y(r, g, b);
1111 U2e = RGB2U(r, g, b);
1112 V2e = RGB2V(r, g, b);
1117 const BYTE r = *srcOdd++;
1118 const BYTE g = *srcOdd++;
1119 const BYTE b = *srcOdd++;
1121 Y1o = Y2o = RGB2Y(r, g, b);
1122 U1o = U2o = RGB2U(r, g, b);
1123 V1o = V2o = RGB2V(r, g, b);
1126 if (b1Odd && !lastX)
1128 const BYTE r = *srcOdd++;
1129 const BYTE g = *srcOdd++;
1130 const BYTE b = *srcOdd++;
1132 Y2o = RGB2Y(r, g, b);
1133 U2o = RGB2U(r, g, b);
1134 V2o = RGB2V(r, g, b);
1150 const BYTE Uavg = ((UINT16)U1e + (UINT16)U2e + (UINT16)U1o + (UINT16)U2o) / 4;
1151 const BYTE Vavg = ((UINT16)V1e + (UINT16)V2e + (UINT16)V1o + (UINT16)V2o) / 4;
1178 static INLINE pstatus_t general_RGBToAVC444YUV_RGBX(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcStep,
1179 BYTE* WINPR_RESTRICT pDst1[3],
1180 const UINT32 dst1Step[3],
1181 BYTE* WINPR_RESTRICT pDst2[3],
1182 const UINT32 dst2Step[3],
1189 const BYTE* pMaxSrc = pSrc + 1ULL * (roi->height - 1) * srcStep;
1191 for (UINT32 y = 0; y < roi->height; y += 2)
1193 const BOOL last = (y >= (roi->height - 1));
1194 const BYTE* srcEven = y < roi->height ? pSrc + 1ULL * y * srcStep : pMaxSrc;
1195 const BYTE* srcOdd = !last ? pSrc + 1ULL * (y + 1) * srcStep : pMaxSrc;
1196 const UINT32 i = y >> 1;
1197 const UINT32 n = (i & ~7) + i;
1198 BYTE* b1Even = pDst1[0] + 1ULL * y * dst1Step[0];
1199 BYTE* b1Odd = !last ? (b1Even + dst1Step[0]) : NULL;
1200 BYTE* b2 = pDst1[1] + 1ULL * (y / 2) * dst1Step[1];
1201 BYTE* b3 = pDst1[2] + 1ULL * (y / 2) * dst1Step[2];
1202 BYTE* b4 = pDst2[0] + 1ULL * dst2Step[0] * n;
1203 BYTE* b5 = b4 + 8ULL * dst2Step[0];
1204 BYTE* b6 = pDst2[1] + 1ULL * (y / 2) * dst2Step[1];
1205 BYTE* b7 = pDst2[2] + 1ULL * (y / 2) * dst2Step[2];
1206 general_RGBToAVC444YUV_RGBX_DOUBLE_ROW(srcEven, srcOdd, b1Even, b1Odd, b2, b3, b4, b5, b6,
1210 return PRIMITIVES_SUCCESS;
1213 static INLINE
void general_RGBToAVC444YUV_ANY_DOUBLE_ROW(
1214 const BYTE* WINPR_RESTRICT srcEven,
const BYTE* WINPR_RESTRICT srcOdd, UINT32 srcFormat,
1215 BYTE* WINPR_RESTRICT b1Even, BYTE* WINPR_RESTRICT b1Odd, BYTE* WINPR_RESTRICT b2,
1216 BYTE* WINPR_RESTRICT b3, BYTE* WINPR_RESTRICT b4, BYTE* WINPR_RESTRICT b5,
1217 BYTE* WINPR_RESTRICT b6, BYTE* WINPR_RESTRICT b7, UINT32 width)
1219 const UINT32 bpp = FreeRDPGetBytesPerPixel(srcFormat);
1220 for (UINT32 x = 0; x < width; x += 2)
1222 const BOOL lastX = (x + 1) >= width;
1240 const UINT32 color = FreeRDPReadColor(srcEven, srcFormat);
1242 FreeRDPSplitColor(color, srcFormat, &r, &g, &b, NULL, NULL);
1243 Y1e = Y2e = Y1o = Y2o = RGB2Y(r, g, b);
1244 U1e = U2e = U1o = U2o = RGB2U(r, g, b);
1245 V1e = V2e = V1o = V2o = RGB2V(r, g, b);
1253 const UINT32 color = FreeRDPReadColor(srcEven, srcFormat);
1255 FreeRDPSplitColor(color, srcFormat, &r, &g, &b, NULL, NULL);
1256 Y2e = RGB2Y(r, g, b);
1257 U2e = RGB2U(r, g, b);
1258 V2e = RGB2V(r, g, b);
1266 const UINT32 color = FreeRDPReadColor(srcOdd, srcFormat);
1268 FreeRDPSplitColor(color, srcFormat, &r, &g, &b, NULL, NULL);
1269 Y1o = Y2o = RGB2Y(r, g, b);
1270 U1o = U2o = RGB2U(r, g, b);
1271 V1o = V2o = RGB2V(r, g, b);
1274 if (b1Odd && !lastX)
1279 const UINT32 color = FreeRDPReadColor(srcOdd, srcFormat);
1281 FreeRDPSplitColor(color, srcFormat, &r, &g, &b, NULL, NULL);
1282 Y2o = RGB2Y(r, g, b);
1283 U2o = RGB2U(r, g, b);
1284 V2o = RGB2V(r, g, b);
1300 const BYTE Uavg = ((UINT16)U1e + (UINT16)U2e + (UINT16)U1o + (UINT16)U2o) / 4;
1301 const BYTE Vavg = ((UINT16)V1e + (UINT16)V2e + (UINT16)V1o + (UINT16)V2o) / 4;
1328 static INLINE pstatus_t general_RGBToAVC444YUV_ANY(
1329 const BYTE* WINPR_RESTRICT pSrc, UINT32 srcFormat, UINT32 srcStep,
1330 BYTE* WINPR_RESTRICT pDst1[3],
const UINT32 dst1Step[3], BYTE* WINPR_RESTRICT pDst2[3],
1331 const UINT32 dst2Step[3],
const prim_size_t* WINPR_RESTRICT roi)
1390 const BYTE* pMaxSrc = pSrc + 1ULL * (roi->height - 1) * srcStep;
1392 for (
size_t y = 0; y < roi->height; y += 2)
1394 WINPR_ASSERT(y < UINT32_MAX);
1396 const BOOL last = (y >= (roi->height - 1));
1397 const BYTE* srcEven = y < roi->height ? pSrc + y * srcStep : pMaxSrc;
1398 const BYTE* srcOdd = !last ? pSrc + (y + 1) * srcStep : pMaxSrc;
1399 const UINT32 i = (UINT32)y >> 1;
1400 const UINT32 n = (i & ~7) + i;
1401 BYTE* b1Even = pDst1[0] + y * dst1Step[0];
1402 BYTE* b1Odd = !last ? (b1Even + dst1Step[0]) : NULL;
1403 BYTE* b2 = pDst1[1] + (y / 2) * dst1Step[1];
1404 BYTE* b3 = pDst1[2] + (y / 2) * dst1Step[2];
1405 BYTE* b4 = pDst2[0] + 1ULL * dst2Step[0] * n;
1406 BYTE* b5 = b4 + 8ULL * dst2Step[0];
1407 BYTE* b6 = pDst2[1] + (y / 2) * dst2Step[1];
1408 BYTE* b7 = pDst2[2] + (y / 2) * dst2Step[2];
1409 general_RGBToAVC444YUV_ANY_DOUBLE_ROW(srcEven, srcOdd, srcFormat, b1Even, b1Odd, b2, b3, b4,
1410 b5, b6, b7, roi->width);
1413 return PRIMITIVES_SUCCESS;
1416 static INLINE pstatus_t general_RGBToAVC444YUV(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcFormat,
1417 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst1[3],
1418 const UINT32 dst1Step[3],
1419 BYTE* WINPR_RESTRICT pDst2[3],
1420 const UINT32 dst2Step[3],
1423 if (!pSrc || !pDst1 || !dst1Step || !pDst2 || !dst2Step)
1426 if (!pDst1[0] || !pDst1[1] || !pDst1[2])
1429 if (!dst1Step[0] || !dst1Step[1] || !dst1Step[2])
1432 if (!pDst2[0] || !pDst2[1] || !pDst2[2])
1435 if (!dst2Step[0] || !dst2Step[1] || !dst2Step[2])
1440 case PIXEL_FORMAT_BGRA32:
1441 case PIXEL_FORMAT_BGRX32:
1442 return general_RGBToAVC444YUV_BGRX(pSrc, srcStep, pDst1, dst1Step, pDst2, dst2Step,
1445 case PIXEL_FORMAT_RGBA32:
1446 case PIXEL_FORMAT_RGBX32:
1447 return general_RGBToAVC444YUV_RGBX(pSrc, srcStep, pDst1, dst1Step, pDst2, dst2Step,
1451 return general_RGBToAVC444YUV_ANY(pSrc, srcFormat, srcStep, pDst1, dst1Step, pDst2,
1455 return !PRIMITIVES_SUCCESS;
1458 static INLINE
void general_RGBToAVC444YUVv2_ANY_DOUBLE_ROW(
1459 const BYTE* WINPR_RESTRICT srcEven,
const BYTE* WINPR_RESTRICT srcOdd, UINT32 srcFormat,
1460 BYTE* WINPR_RESTRICT yLumaDstEven, BYTE* WINPR_RESTRICT yLumaDstOdd,
1461 BYTE* WINPR_RESTRICT uLumaDst, BYTE* WINPR_RESTRICT vLumaDst,
1462 BYTE* WINPR_RESTRICT yEvenChromaDst1, BYTE* WINPR_RESTRICT yEvenChromaDst2,
1463 BYTE* WINPR_RESTRICT yOddChromaDst1, BYTE* WINPR_RESTRICT yOddChromaDst2,
1464 BYTE* WINPR_RESTRICT uChromaDst1, BYTE* WINPR_RESTRICT uChromaDst2,
1465 BYTE* WINPR_RESTRICT vChromaDst1, BYTE* WINPR_RESTRICT vChromaDst2, UINT32 width)
1467 const UINT32 bpp = FreeRDPGetBytesPerPixel(srcFormat);
1469 for (UINT32 x = 0; x < width; x += 2)
1487 const UINT32 color = FreeRDPReadColor(srcEven, srcFormat);
1489 FreeRDPSplitColor(color, srcFormat, &r, &g, &b, NULL, NULL);
1490 Ya = RGB2Y(r, g, b);
1491 Ua = RGB2U(r, g, b);
1492 Va = RGB2V(r, g, b);
1500 const UINT32 color = FreeRDPReadColor(srcEven, srcFormat);
1502 FreeRDPSplitColor(color, srcFormat, &r, &g, &b, NULL, NULL);
1503 Yb = RGB2Y(r, g, b);
1504 Ub = RGB2U(r, g, b);
1505 Vb = RGB2V(r, g, b);
1519 const UINT32 color = FreeRDPReadColor(srcOdd, srcFormat);
1521 FreeRDPSplitColor(color, srcFormat, &r, &g, &b, NULL, NULL);
1522 Yc = RGB2Y(r, g, b);
1523 Uc = RGB2U(r, g, b);
1524 Vc = RGB2V(r, g, b);
1533 if (srcOdd && (x < width - 1))
1538 const UINT32 color = FreeRDPReadColor(srcOdd, srcFormat);
1540 FreeRDPSplitColor(color, srcFormat, &r, &g, &b, NULL, NULL);
1541 Yd = RGB2Y(r, g, b);
1542 Ud = RGB2U(r, g, b);
1543 Vd = RGB2V(r, g, b);
1553 *yLumaDstEven++ = Ya;
1556 *yLumaDstEven++ = Yb;
1559 *yLumaDstOdd++ = Yc;
1561 if (srcOdd && (x < width - 1))
1562 *yLumaDstOdd++ = Yd;
1565 *uLumaDst++ = (Ua + Ub + Uc + Ud) / 4;
1566 *vLumaDst++ = (Va + Vb + Vc + Vd) / 4;
1571 *yEvenChromaDst1++ = Ub;
1572 *yEvenChromaDst2++ = Vb;
1580 *yOddChromaDst1++ = Ud;
1581 *yOddChromaDst2++ = Vd;
1587 *uChromaDst1++ = Uc;
1588 *uChromaDst2++ = Vc;
1593 *vChromaDst1++ = Uc;
1594 *vChromaDst2++ = Vc;
1600 static INLINE pstatus_t general_RGBToAVC444YUVv2_ANY(
1601 const BYTE* WINPR_RESTRICT pSrc, UINT32 srcFormat, UINT32 srcStep,
1602 BYTE* WINPR_RESTRICT pDst1[3],
const UINT32 dst1Step[3], BYTE* WINPR_RESTRICT pDst2[3],
1603 const UINT32 dst2Step[3],
const prim_size_t* WINPR_RESTRICT roi)
1655 if (roi->height < 1 || roi->width < 1)
1656 return !PRIMITIVES_SUCCESS;
1658 for (
size_t y = 0; y < roi->height; y += 2)
1660 const BYTE* srcEven = (pSrc + y * srcStep);
1661 const BYTE* srcOdd = (y < roi->height - 1) ? (srcEven + srcStep) : NULL;
1662 BYTE* dstLumaYEven = (pDst1[0] + y * dst1Step[0]);
1663 BYTE* dstLumaYOdd = (dstLumaYEven + dst1Step[0]);
1664 BYTE* dstLumaU = (pDst1[1] + (y / 2) * dst1Step[1]);
1665 BYTE* dstLumaV = (pDst1[2] + (y / 2) * dst1Step[2]);
1666 BYTE* dstEvenChromaY1 = (pDst2[0] + y * dst2Step[0]);
1667 BYTE* dstEvenChromaY2 = dstEvenChromaY1 + roi->width / 2;
1668 BYTE* dstOddChromaY1 = dstEvenChromaY1 + dst2Step[0];
1669 BYTE* dstOddChromaY2 = dstEvenChromaY2 + dst2Step[0];
1670 BYTE* dstChromaU1 = (pDst2[1] + (y / 2) * dst2Step[1]);
1671 BYTE* dstChromaV1 = (pDst2[2] + (y / 2) * dst2Step[2]);
1672 BYTE* dstChromaU2 = dstChromaU1 + roi->width / 4;
1673 BYTE* dstChromaV2 = dstChromaV1 + roi->width / 4;
1674 general_RGBToAVC444YUVv2_ANY_DOUBLE_ROW(
1675 srcEven, srcOdd, srcFormat, dstLumaYEven, dstLumaYOdd, dstLumaU, dstLumaV,
1676 dstEvenChromaY1, dstEvenChromaY2, dstOddChromaY1, dstOddChromaY2, dstChromaU1,
1677 dstChromaU2, dstChromaV1, dstChromaV2, roi->width);
1680 return PRIMITIVES_SUCCESS;
1683 static INLINE
void general_RGBToAVC444YUVv2_BGRX_DOUBLE_ROW(
1684 const BYTE* WINPR_RESTRICT srcEven,
const BYTE* WINPR_RESTRICT srcOdd,
1685 BYTE* WINPR_RESTRICT yLumaDstEven, BYTE* WINPR_RESTRICT yLumaDstOdd,
1686 BYTE* WINPR_RESTRICT uLumaDst, BYTE* WINPR_RESTRICT vLumaDst,
1687 BYTE* WINPR_RESTRICT yEvenChromaDst1, BYTE* WINPR_RESTRICT yEvenChromaDst2,
1688 BYTE* WINPR_RESTRICT yOddChromaDst1, BYTE* WINPR_RESTRICT yOddChromaDst2,
1689 BYTE* WINPR_RESTRICT uChromaDst1, BYTE* WINPR_RESTRICT uChromaDst2,
1690 BYTE* WINPR_RESTRICT vChromaDst1, BYTE* WINPR_RESTRICT vChromaDst2, UINT32 width)
1692 for (UINT32 x = 0; x < width; x += 2)
1707 const BYTE b = *srcEven++;
1708 const BYTE g = *srcEven++;
1709 const BYTE r = *srcEven++;
1711 Ya = RGB2Y(r, g, b);
1712 Ua = RGB2U(r, g, b);
1713 Va = RGB2V(r, g, b);
1718 const BYTE b = *srcEven++;
1719 const BYTE g = *srcEven++;
1720 const BYTE r = *srcEven++;
1722 Yb = RGB2Y(r, g, b);
1723 Ub = RGB2U(r, g, b);
1724 Vb = RGB2V(r, g, b);
1735 const BYTE b = *srcOdd++;
1736 const BYTE g = *srcOdd++;
1737 const BYTE r = *srcOdd++;
1739 Yc = RGB2Y(r, g, b);
1740 Uc = RGB2U(r, g, b);
1741 Vc = RGB2V(r, g, b);
1750 if (srcOdd && (x < width - 1))
1752 const BYTE b = *srcOdd++;
1753 const BYTE g = *srcOdd++;
1754 const BYTE r = *srcOdd++;
1756 Yd = RGB2Y(r, g, b);
1757 Ud = RGB2U(r, g, b);
1758 Vd = RGB2V(r, g, b);
1768 *yLumaDstEven++ = Ya;
1771 *yLumaDstEven++ = Yb;
1774 *yLumaDstOdd++ = Yc;
1776 if (srcOdd && (x < width - 1))
1777 *yLumaDstOdd++ = Yd;
1780 *uLumaDst++ = (Ua + Ub + Uc + Ud) / 4;
1781 *vLumaDst++ = (Va + Vb + Vc + Vd) / 4;
1786 *yEvenChromaDst1++ = Ub;
1787 *yEvenChromaDst2++ = Vb;
1795 *yOddChromaDst1++ = Ud;
1796 *yOddChromaDst2++ = Vd;
1802 *uChromaDst1++ = Uc;
1803 *uChromaDst2++ = Vc;
1808 *vChromaDst1++ = Uc;
1809 *vChromaDst2++ = Vc;
1815 static INLINE pstatus_t general_RGBToAVC444YUVv2_BGRX(
const BYTE* WINPR_RESTRICT pSrc,
1816 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst1[3],
1817 const UINT32 dst1Step[3],
1818 BYTE* WINPR_RESTRICT pDst2[3],
1819 const UINT32 dst2Step[3],
1822 if (roi->height < 1 || roi->width < 1)
1823 return !PRIMITIVES_SUCCESS;
1825 for (
size_t y = 0; y < roi->height; y += 2)
1827 const BYTE* srcEven = (pSrc + y * srcStep);
1828 const BYTE* srcOdd = (y < roi->height - 1) ? (srcEven + srcStep) : NULL;
1829 BYTE* dstLumaYEven = (pDst1[0] + y * dst1Step[0]);
1830 BYTE* dstLumaYOdd = (dstLumaYEven + dst1Step[0]);
1831 BYTE* dstLumaU = (pDst1[1] + (y / 2) * dst1Step[1]);
1832 BYTE* dstLumaV = (pDst1[2] + (y / 2) * dst1Step[2]);
1833 BYTE* dstEvenChromaY1 = (pDst2[0] + y * dst2Step[0]);
1834 BYTE* dstEvenChromaY2 = dstEvenChromaY1 + roi->width / 2;
1835 BYTE* dstOddChromaY1 = dstEvenChromaY1 + dst2Step[0];
1836 BYTE* dstOddChromaY2 = dstEvenChromaY2 + dst2Step[0];
1837 BYTE* dstChromaU1 = (pDst2[1] + (y / 2) * dst2Step[1]);
1838 BYTE* dstChromaV1 = (pDst2[2] + (y / 2) * dst2Step[2]);
1839 BYTE* dstChromaU2 = dstChromaU1 + roi->width / 4;
1840 BYTE* dstChromaV2 = dstChromaV1 + roi->width / 4;
1841 general_RGBToAVC444YUVv2_BGRX_DOUBLE_ROW(
1842 srcEven, srcOdd, dstLumaYEven, dstLumaYOdd, dstLumaU, dstLumaV, dstEvenChromaY1,
1843 dstEvenChromaY2, dstOddChromaY1, dstOddChromaY2, dstChromaU1, dstChromaU2, dstChromaV1,
1844 dstChromaV2, roi->width);
1847 return PRIMITIVES_SUCCESS;
1850 static INLINE pstatus_t general_RGBToAVC444YUVv2(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcFormat,
1851 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst1[3],
1852 const UINT32 dst1Step[3],
1853 BYTE* WINPR_RESTRICT pDst2[3],
1854 const UINT32 dst2Step[3],
1859 case PIXEL_FORMAT_BGRA32:
1860 case PIXEL_FORMAT_BGRX32:
1861 return general_RGBToAVC444YUVv2_BGRX(pSrc, srcStep, pDst1, dst1Step, pDst2, dst2Step,
1865 return general_RGBToAVC444YUVv2_ANY(pSrc, srcFormat, srcStep, pDst1, dst1Step, pDst2,
1869 return !PRIMITIVES_SUCCESS;
1872 void primitives_init_YUV(
primitives_t* WINPR_RESTRICT prims)
1874 prims->YUV420ToRGB_8u_P3AC4R = general_YUV420ToRGB_8u_P3AC4R;
1875 prims->YUV444ToRGB_8u_P3AC4R = general_YUV444ToRGB_8u_P3AC4R;
1876 prims->RGBToYUV420_8u_P3AC4R = general_RGBToYUV420_8u_P3AC4R;
1877 prims->RGBToYUV444_8u_P3AC4R = general_RGBToYUV444_8u_P3AC4R;
1878 prims->YUV420CombineToYUV444 = general_YUV420CombineToYUV444;
1879 prims->YUV444SplitToYUV420 = general_YUV444SplitToYUV420;
1880 prims->RGBToAVC444YUV = general_RGBToAVC444YUV;
1881 prims->RGBToAVC444YUVv2 = general_RGBToAVC444YUVv2;
1884 void primitives_init_YUV_opt(
primitives_t* WINPR_RESTRICT prims)
1886 primitives_init_YUV_ssse3(prims);
1887 primitives_init_YUV_neon(prims);