24 #include <winpr/wtypes.h>
25 #include <winpr/assert.h>
26 #include <winpr/cast.h>
28 #include <freerdp/config.h>
30 #include <freerdp/types.h>
31 #include <freerdp/primitives.h>
32 #include <freerdp/codec/color.h>
33 #include "prim_internal.h"
36 static pstatus_t general_LumaToYUV444(
const BYTE* WINPR_RESTRICT pSrcRaw[3],
37 const UINT32 srcStep[3], BYTE* WINPR_RESTRICT pDstRaw[3],
38 const UINT32 dstStep[3],
41 const UINT32 nWidth = roi->right - roi->left;
42 const UINT32 nHeight = roi->bottom - roi->top;
43 const UINT32 halfWidth = (nWidth + 1) / 2;
44 const UINT32 halfHeight = (nHeight + 1) / 2;
45 const UINT32 oddY = 1;
46 const UINT32 evenY = 0;
47 const UINT32 oddX = 1;
48 const UINT32 evenX = 0;
49 const BYTE* pSrc[3] = { pSrcRaw[0] + 1ULL * roi->top * srcStep[0] + roi->left,
50 pSrcRaw[1] + 1ULL * roi->top / 2 * srcStep[1] + roi->left / 2,
51 pSrcRaw[2] + 1ULL * roi->top / 2 * srcStep[2] + roi->left / 2 };
52 BYTE* pDst[3] = { pDstRaw[0] + 1ULL * roi->top * dstStep[0] + roi->left,
53 pDstRaw[1] + 1ULL * roi->top * dstStep[1] + roi->left,
54 pDstRaw[2] + 1ULL * roi->top * dstStep[2] + roi->left };
58 for (
size_t y = 0; y < nHeight; y++)
60 const BYTE* Ym = pSrc[0] + y * srcStep[0];
61 BYTE* pY = pDst[0] + dstStep[0] * y;
62 memcpy(pY, Ym, nWidth);
67 for (UINT32 y = 0; y < halfHeight; y++)
69 const UINT32 val2y = (2UL * y + evenY);
70 const UINT32 val2y1 = val2y + oddY;
71 const BYTE* Um = pSrc[1] + 1ULL * y * srcStep[1];
72 const BYTE* Vm = pSrc[2] + 1ULL * y * srcStep[2];
73 BYTE* pU = pDst[1] + 1ULL * dstStep[1] * val2y;
74 BYTE* pV = pDst[2] + 1ULL * dstStep[2] * val2y;
75 BYTE* pU1 = pDst[1] + 1ULL * dstStep[1] * val2y1;
76 BYTE* pV1 = pDst[2] + 1ULL * dstStep[2] * val2y1;
78 for (UINT32 x = 0; x < halfWidth; x++)
80 const UINT32 val2x = 2UL * x + evenX;
81 const UINT32 val2x1 = val2x + oddX;
93 return PRIMITIVES_SUCCESS;
96 static pstatus_t general_ChromaFilter(BYTE* WINPR_RESTRICT pDst[3],
const UINT32 dstStep[3],
99 const UINT32 oddY = 1;
100 const UINT32 evenY = 0;
101 const UINT32 nWidth = roi->right - roi->left;
102 const UINT32 nHeight = roi->bottom - roi->top;
103 const UINT32 halfHeight = (nHeight + 1) / 2;
104 const UINT32 halfWidth = (nWidth + 1) / 2;
107 for (UINT32 y = roi->top; y < halfHeight + roi->top; y++)
109 const UINT32 val2y = (y * 2 + evenY);
110 const UINT32 val2y1 = val2y + oddY;
111 BYTE* pU1 = pDst[1] + 1ULL * dstStep[1] * val2y1;
112 BYTE* pV1 = pDst[2] + 1ULL * dstStep[2] * val2y1;
113 BYTE* pU = pDst[1] + 1ULL * dstStep[1] * val2y;
114 BYTE* pV = pDst[2] + 1ULL * dstStep[2] * val2y;
116 if (val2y1 > nHeight)
119 for (UINT32 x = roi->left; x < halfWidth + roi->left; x++)
121 const UINT32 val2x = (x * 2);
122 const UINT32 val2x1 = val2x + 1;
123 const BYTE inU = pU[val2x];
124 const BYTE inV = pV[val2x];
125 const INT32 up = inU * 4;
126 const INT32 vp = inV * 4;
133 u2020 = up - pU[val2x1] - pU1[val2x] - pU1[val2x1];
134 v2020 = vp - pV[val2x1] - pV1[val2x] - pV1[val2x1];
136 pU[val2x] = CONDITIONAL_CLIP(u2020, inU);
137 pV[val2x] = CONDITIONAL_CLIP(v2020, inV);
141 return PRIMITIVES_SUCCESS;
144 static pstatus_t general_ChromaV1ToYUV444(
const BYTE* WINPR_RESTRICT pSrcRaw[3],
145 const UINT32 srcStep[3], BYTE* WINPR_RESTRICT pDstRaw[3],
146 const UINT32 dstStep[3],
149 const UINT32 mod = 16;
152 const UINT32 nWidth = roi->right - roi->left;
153 const UINT32 nHeight = roi->bottom - roi->top;
154 const UINT32 halfWidth = (nWidth) / 2;
155 const UINT32 halfHeight = (nHeight) / 2;
156 const UINT32 oddY = 1;
157 const UINT32 evenY = 0;
158 const UINT32 oddX = 1;
161 const UINT32 padHeigth = nHeight + 16 - nHeight % 16;
162 const BYTE* pSrc[3] = { pSrcRaw[0] + 1ULL * roi->top * srcStep[0] + roi->left,
163 pSrcRaw[1] + 1ULL * roi->top / 2 * srcStep[1] + roi->left / 2,
164 pSrcRaw[2] + 1ULL * roi->top / 2 * srcStep[2] + roi->left / 2 };
165 BYTE* pDst[3] = { pDstRaw[0] + 1ULL * roi->top * dstStep[0] + roi->left,
166 pDstRaw[1] + 1ULL * roi->top * dstStep[1] + roi->left,
167 pDstRaw[2] + 1ULL * roi->top * dstStep[2] + roi->left };
171 for (
size_t y = 0; y < padHeigth; y++)
173 const BYTE* Ya = pSrc[0] + y * srcStep[0];
176 if ((y) % mod < (mod + 1) / 2)
178 const size_t pos = (2 * uY++ + oddY);
183 pX = pDst[1] + dstStep[1] * pos;
187 const size_t pos = (2 * vY++ + oddY);
192 pX = pDst[2] + dstStep[2] * pos;
195 memcpy(pX, Ya, nWidth);
199 for (UINT32 y = 0; y < halfHeight; y++)
201 const UINT32 val2y = (y * 2UL + evenY);
202 const BYTE* Ua = pSrc[1] + 1ULL * y * srcStep[1];
203 const BYTE* Va = pSrc[2] + 1ULL * y * srcStep[2];
204 BYTE* pU = pDst[1] + 1ULL * dstStep[1] * val2y;
205 BYTE* pV = pDst[2] + 1ULL * dstStep[2] * val2y;
207 for (UINT32 x = 0; x < halfWidth; x++)
209 const UINT32 val2x1 = (x * 2 + oddX);
216 return general_ChromaFilter(pDst, dstStep, roi);
219 static pstatus_t general_ChromaV2ToYUV444(
const BYTE* WINPR_RESTRICT pSrc[3],
220 const UINT32 srcStep[3], UINT32 nTotalWidth,
221 UINT32 nTotalHeight, BYTE* WINPR_RESTRICT pDst[3],
222 const UINT32 dstStep[3],
225 const UINT32 nWidth = roi->right - roi->left;
226 const UINT32 nHeight = roi->bottom - roi->top;
227 const UINT32 halfWidth = (nWidth + 1) / 2;
228 const UINT32 halfHeight = (nHeight + 1) / 2;
229 const UINT32 quaterWidth = (nWidth + 3) / 4;
232 for (UINT32 y = 0; y < nHeight; y++)
234 const UINT32 yTop = y + roi->top;
235 const BYTE* pYaU = pSrc[0] + 1ULL * srcStep[0] * yTop + roi->left / 2;
236 const BYTE* pYaV = pYaU + nTotalWidth / 2;
237 BYTE* pU = pDst[1] + 1ULL * dstStep[1] * yTop + roi->left;
238 BYTE* pV = pDst[2] + 1ULL * dstStep[2] * yTop + roi->left;
240 for (UINT32 x = 0; x < halfWidth; x++)
242 const UINT32 odd = 2UL * x + 1UL;
249 for (
size_t y = 0; y < halfHeight; y++)
251 const BYTE* pUaU = pSrc[1] + srcStep[1] * (y + roi->top / 2) + roi->left / 4;
252 const BYTE* pUaV = pUaU + nTotalWidth / 4;
253 const BYTE* pVaU = pSrc[2] + srcStep[2] * (y + roi->top / 2) + roi->left / 4;
254 const BYTE* pVaV = pVaU + nTotalWidth / 4;
255 BYTE* pU = pDst[1] + 1ULL * dstStep[1] * (2ULL * y + 1 + roi->top) + roi->left;
256 BYTE* pV = pDst[2] + 1ULL * dstStep[2] * (2ULL * y + 1 + roi->top) + roi->left;
258 for (
size_t x = 0; x < quaterWidth; x++)
260 pU[4 * x + 0] = *pUaU++;
261 pV[4 * x + 0] = *pUaV++;
262 pU[4 * x + 2] = *pVaU++;
263 pV[4 * x + 2] = *pVaV++;
267 return general_ChromaFilter(pDst, dstStep, roi);
270 static pstatus_t general_YUV420CombineToYUV444(avc444_frame_type type,
271 const BYTE* WINPR_RESTRICT pSrc[3],
272 const UINT32 srcStep[3], UINT32 nWidth,
273 UINT32 nHeight, BYTE* WINPR_RESTRICT pDst[3],
274 const UINT32 dstStep[3],
277 if (!pSrc || !pSrc[0] || !pSrc[1] || !pSrc[2])
280 if (!pDst || !pDst[0] || !pDst[1] || !pDst[2])
289 return general_LumaToYUV444(pSrc, srcStep, pDst, dstStep, roi);
291 case AVC444_CHROMAv1:
292 return general_ChromaV1ToYUV444(pSrc, srcStep, pDst, dstStep, roi);
294 case AVC444_CHROMAv2:
295 return general_ChromaV2ToYUV444(pSrc, srcStep, nWidth, nHeight, pDst, dstStep, roi);
303 general_YUV444SplitToYUV420(
const BYTE* WINPR_RESTRICT pSrc[3],
const UINT32 srcStep[3],
304 BYTE* WINPR_RESTRICT pMainDst[3],
const UINT32 dstMainStep[3],
305 BYTE* WINPR_RESTRICT pAuxDst[3],
const UINT32 dstAuxStep[3],
310 UINT32 halfWidth = 0;
311 UINT32 halfHeight = 0;
314 const UINT32 padHeigth = roi->height + 16 - roi->height % 16;
315 halfWidth = (roi->width + 1) / 2;
316 halfHeight = (roi->height + 1) / 2;
319 for (
size_t y = 0; y < roi->height; y++)
321 const BYTE* pSrcY = pSrc[0] + y * srcStep[0];
322 BYTE* pY = pMainDst[0] + y * dstMainStep[0];
323 memcpy(pY, pSrcY, roi->width);
327 for (
size_t y = 0; y < halfHeight; y++)
329 const BYTE* pSrcU = pSrc[1] + 2ULL * y * srcStep[1];
330 const BYTE* pSrcV = pSrc[2] + 2ULL * y * srcStep[2];
331 const BYTE* pSrcU1 = pSrc[1] + (2ULL * y + 1ULL) * srcStep[1];
332 const BYTE* pSrcV1 = pSrc[2] + (2ULL * y + 1ULL) * srcStep[2];
333 BYTE* pU = pMainDst[1] + y * dstMainStep[1];
334 BYTE* pV = pMainDst[2] + y * dstMainStep[2];
336 for (
size_t x = 0; x < halfWidth; x++)
339 const INT32 u = pSrcU[2 * x] + pSrcU[2 * x + 1] + pSrcU1[2 * x] + pSrcU1[2 * x + 1];
340 const INT32 v = pSrcV[2 * x] + pSrcV[2 * x + 1] + pSrcV1[2 * x] + pSrcV1[2 * x + 1];
341 pU[x] = CLIP(u / 4L);
342 pV[x] = CLIP(v / 4L);
347 for (
size_t y = 0; y < padHeigth; y++)
349 BYTE* pY = pAuxDst[0] + y * dstAuxStep[0];
353 const size_t pos = (2 * uY++ + 1);
354 const BYTE* pSrcU = pSrc[1] + pos * srcStep[1];
356 if (pos >= roi->height)
359 memcpy(pY, pSrcU, roi->width);
363 const size_t pos = (2 * vY++ + 1);
364 const BYTE* pSrcV = pSrc[2] + pos * srcStep[2];
366 if (pos >= roi->height)
369 memcpy(pY, pSrcV, roi->width);
374 for (
size_t y = 0; y < halfHeight; y++)
376 const BYTE* pSrcU = pSrc[1] + 2 * y * srcStep[1];
377 const BYTE* pSrcV = pSrc[2] + 2 * y * srcStep[2];
378 BYTE* pU = pAuxDst[1] + y * dstAuxStep[1];
379 BYTE* pV = pAuxDst[2] + y * dstAuxStep[2];
381 for (
size_t x = 0; x < halfWidth; x++)
383 pU[x] = pSrcU[2 * x + 1];
384 pV[x] = pSrcV[2 * x + 1];
388 return PRIMITIVES_SUCCESS;
391 static pstatus_t general_YUV444ToRGB_8u_P3AC4R_general(
const BYTE* WINPR_RESTRICT pSrc[3],
392 const UINT32 srcStep[3],
393 BYTE* WINPR_RESTRICT pDst, UINT32 dstStep,
397 const DWORD formatSize = FreeRDPGetBytesPerPixel(DstFormat);
398 fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, FALSE);
404 const UINT32 nWidth = roi->width;
405 const UINT32 nHeight = roi->height;
407 for (
size_t y = 0; y < nHeight; y++)
409 const BYTE* pY = pSrc[0] + y * srcStep[0];
410 const BYTE* pU = pSrc[1] + y * srcStep[1];
411 const BYTE* pV = pSrc[2] + y * srcStep[2];
412 BYTE* pRGB = pDst + y * dstStep;
414 for (
size_t x = 0; x < nWidth; x++)
416 const BYTE Y = pY[x];
417 const BYTE U = pU[x];
418 const BYTE V = pV[x];
419 const BYTE r = YUV2R(Y, U, V);
420 const BYTE g = YUV2G(Y, U, V);
421 const BYTE b = YUV2B(Y, U, V);
422 pRGB = writePixel(pRGB, formatSize, DstFormat, r, g, b, 0);
426 return PRIMITIVES_SUCCESS;
429 static pstatus_t general_YUV444ToRGB_8u_P3AC4R_BGRX(
const BYTE* WINPR_RESTRICT pSrc[3],
430 const UINT32 srcStep[3],
431 BYTE* WINPR_RESTRICT pDst, UINT32 dstStep,
435 const DWORD formatSize = FreeRDPGetBytesPerPixel(DstFormat);
441 const UINT32 nWidth = roi->width;
442 const UINT32 nHeight = roi->height;
444 for (
size_t y = 0; y < nHeight; y++)
446 const BYTE* pY = pSrc[0] + y * srcStep[0];
447 const BYTE* pU = pSrc[1] + y * srcStep[1];
448 const BYTE* pV = pSrc[2] + y * srcStep[2];
449 BYTE* pRGB = pDst + y * dstStep;
451 for (
size_t x = 0; x < nWidth; x++)
453 const BYTE Y = pY[x];
454 const BYTE U = pU[x];
455 const BYTE V = pV[x];
456 const BYTE r = YUV2R(Y, U, V);
457 const BYTE g = YUV2G(Y, U, V);
458 const BYTE b = YUV2B(Y, U, V);
459 pRGB = writePixelBGRX(pRGB, formatSize, DstFormat, r, g, b, 0);
463 return PRIMITIVES_SUCCESS;
466 static pstatus_t general_YUV444ToRGB_8u_P3AC4R(
const BYTE* WINPR_RESTRICT pSrc[3],
467 const UINT32 srcStep[3], BYTE* WINPR_RESTRICT pDst,
468 UINT32 dstStep, UINT32 DstFormat,
473 case PIXEL_FORMAT_BGRA32:
474 case PIXEL_FORMAT_BGRX32:
475 return general_YUV444ToRGB_8u_P3AC4R_BGRX(pSrc, srcStep, pDst, dstStep, DstFormat, roi);
478 return general_YUV444ToRGB_8u_P3AC4R_general(pSrc, srcStep, pDst, dstStep, DstFormat,
487 static pstatus_t general_YUV420ToRGB_8u_P3AC4R(
const BYTE* WINPR_RESTRICT pSrc[3],
488 const UINT32 srcStep[3], BYTE* WINPR_RESTRICT pDst,
489 UINT32 dstStep, UINT32 DstFormat,
497 UINT32 halfWidth = 0;
498 UINT32 halfHeight = 0;
499 const BYTE* pY = NULL;
500 const BYTE* pU = NULL;
501 const BYTE* pV = NULL;
507 const DWORD formatSize = FreeRDPGetBytesPerPixel(DstFormat);
508 fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, FALSE);
512 lastCol = roi->width & 0x01;
513 lastRow = roi->height & 0x01;
514 nWidth = (roi->width + 1) & (uint32_t)~0x0001;
515 nHeight = (roi->height + 1) & (uint32_t)~0x0001;
516 halfWidth = nWidth / 2;
517 halfHeight = nHeight / 2;
518 srcPad[0] = (srcStep[0] - nWidth);
519 srcPad[1] = (srcStep[1] - halfWidth);
520 srcPad[2] = (srcStep[2] - halfWidth);
521 dstPad = (dstStep - (nWidth * 4));
523 for (UINT32 y = 0; y < halfHeight;)
525 if (++y == halfHeight)
528 for (UINT32 x = 0; x < halfWidth;)
534 if (++x == halfWidth)
544 pRGB = writePixel(pRGB, formatSize, DstFormat, r, g, b, 0);
547 if (!(lastCol & 0x02))
553 pRGB = writePixel(pRGB, formatSize, DstFormat, r, g, b, 0);
571 for (UINT32 x = 0; x < halfWidth;)
577 if (++x == halfWidth)
587 pRGB = writePixel(pRGB, formatSize, DstFormat, r, g, b, 0);
590 if (!(lastCol & 0x02))
596 pRGB = writePixel(pRGB, formatSize, DstFormat, r, g, b, 0);
612 return PRIMITIVES_SUCCESS;
620 static INLINE BYTE RGB2Y(INT32 R, INT32 G, INT32 B)
622 const INT32 val = ((54 * R + 183 * G + 18 * B) >> 8);
623 return WINPR_ASSERTING_INT_CAST(BYTE, val);
626 static INLINE BYTE RGB2U(INT32 R, INT32 G, INT32 B)
628 const INT32 val = (((-29 * R - 99 * G + 128 * B) >> 8) + 128);
629 return WINPR_ASSERTING_INT_CAST(BYTE, val);
632 static INLINE BYTE RGB2V(INT32 R, INT32 G, INT32 B)
634 const INT32 val = (((128 * R - 116 * G - 12 * B) >> 8) + 128);
635 return WINPR_ASSERTING_INT_CAST(BYTE, val);
639 static pstatus_t general_RGBToYUV444_8u_P3AC4R(
const BYTE* WINPR_RESTRICT pSrc, UINT32 SrcFormat,
640 const UINT32 srcStep, BYTE* WINPR_RESTRICT pDst[3],
645 const UINT32 bpp = FreeRDPGetBytesPerPixel(SrcFormat);
649 nHeight = roi->height;
651 for (
size_t y = 0; y < nHeight; y++)
653 const BYTE* pRGB = pSrc + y * srcStep;
654 BYTE* pY = pDst[0] + y * dstStep[0];
655 BYTE* pU = pDst[1] + y * dstStep[1];
656 BYTE* pV = pDst[2] + y * dstStep[2];
658 for (
size_t x = 0; x < nWidth; x++)
663 const UINT32 color = FreeRDPReadColor(&pRGB[x * bpp], SrcFormat);
664 FreeRDPSplitColor(color, SrcFormat, &R, &G, &B, NULL, NULL);
665 pY[x] = RGB2Y(R, G, B);
666 pU[x] = RGB2U(R, G, B);
667 pV[x] = RGB2V(R, G, B);
671 return PRIMITIVES_SUCCESS;
674 static INLINE pstatus_t general_RGBToYUV420_BGRX(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcStep,
675 BYTE* WINPR_RESTRICT pDst[3],
676 const UINT32 dstStep[3],
683 size_t x4 = srcStep + 4;
686 size_t y3 = dstStep[0];
687 size_t y4 = dstStep[0] + 1;
688 UINT32 max_x = roi->width - 1;
689 UINT32 max_y = roi->height - 1;
691 for (
size_t y = i = 0; y < roi->height; y += 2, i++)
693 const BYTE* src = pSrc + y * srcStep;
694 BYTE* ydst = pDst[0] + y * dstStep[0];
695 BYTE* udst = pDst[1] + i * dstStep[1];
696 BYTE* vdst = pDst[2] + i * dstStep[2];
698 for (
size_t x = 0; x < roi->width; x += 2)
707 Ba = B = *(src + x1 + 0);
708 Ga = G = *(src + x1 + 1);
709 Ra = R = *(src + x1 + 2);
710 ydst[y1] = RGB2Y(R, G, B);
715 Ba += B = *(src + x2 + 0);
716 Ga += G = *(src + x2 + 1);
717 Ra += R = *(src + x2 + 2);
718 ydst[y2] = RGB2Y(R, G, B);
724 Ba += B = *(src + x3 + 0);
725 Ga += G = *(src + x3 + 1);
726 Ra += R = *(src + x3 + 2);
727 ydst[y3] = RGB2Y(R, G, B);
732 Ba += B = *(src + x4 + 0);
733 Ga += G = *(src + x4 + 1);
734 Ra += R = *(src + x4 + 2);
735 ydst[y4] = RGB2Y(R, G, B);
742 *udst++ = RGB2U(Ra, Ga, Ba);
743 *vdst++ = RGB2V(Ra, Ga, Ba);
749 return PRIMITIVES_SUCCESS;
752 static INLINE pstatus_t general_RGBToYUV420_RGBX(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcStep,
753 BYTE* WINPR_RESTRICT pDst[3],
754 const UINT32 dstStep[3],
760 size_t x4 = srcStep + 4;
763 size_t y3 = dstStep[0];
764 size_t y4 = dstStep[0] + 1;
765 UINT32 max_x = roi->width - 1;
766 UINT32 max_y = roi->height - 1;
768 for (
size_t y = 0, i = 0; y < roi->height; y += 2, i++)
770 const BYTE* src = pSrc + y * srcStep;
771 BYTE* ydst = pDst[0] + y * dstStep[0];
772 BYTE* udst = pDst[1] + i * dstStep[1];
773 BYTE* vdst = pDst[2] + i * dstStep[2];
775 for (UINT32 x = 0; x < roi->width; x += 2)
777 BYTE R = *(src + x1 + 0);
778 BYTE G = *(src + x1 + 1);
779 BYTE B = *(src + x1 + 2);
784 ydst[y1] = RGB2Y(R, G, B);
795 ydst[y2] = RGB2Y(R, G, B);
808 ydst[y3] = RGB2Y(R, G, B);
820 ydst[y4] = RGB2Y(R, G, B);
827 *udst++ = RGB2U(Ra, Ga, Ba);
828 *vdst++ = RGB2V(Ra, Ga, Ba);
834 return PRIMITIVES_SUCCESS;
837 static INLINE pstatus_t general_RGBToYUV420_ANY(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcFormat,
838 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst[3],
839 const UINT32 dstStep[3],
842 const UINT32 bpp = FreeRDPGetBytesPerPixel(srcFormat);
846 size_t x4 = srcStep + bpp;
849 size_t y3 = dstStep[0];
850 size_t y4 = dstStep[0] + 1;
851 UINT32 max_x = roi->width - 1;
852 UINT32 max_y = roi->height - 1;
854 for (
size_t y = 0, i = 0; y < roi->height; y += 2, i++)
856 const BYTE* src = pSrc + y * srcStep;
857 BYTE* ydst = pDst[0] + y * dstStep[0];
858 BYTE* udst = pDst[1] + i * dstStep[1];
859 BYTE* vdst = pDst[2] + i * dstStep[2];
861 for (
size_t x = 0; x < roi->width; x += 2)
871 color = FreeRDPReadColor(src + x1, srcFormat);
872 FreeRDPSplitColor(color, srcFormat, &R, &G, &B, NULL, NULL);
876 ydst[y1] = RGB2Y(R, G, B);
881 color = FreeRDPReadColor(src + x2, srcFormat);
882 FreeRDPSplitColor(color, srcFormat, &R, &G, &B, NULL, NULL);
886 ydst[y2] = RGB2Y(R, G, B);
892 color = FreeRDPReadColor(src + x3, srcFormat);
893 FreeRDPSplitColor(color, srcFormat, &R, &G, &B, NULL, NULL);
897 ydst[y3] = RGB2Y(R, G, B);
902 color = FreeRDPReadColor(src + x4, srcFormat);
903 FreeRDPSplitColor(color, srcFormat, &R, &G, &B, NULL, NULL);
907 ydst[y4] = RGB2Y(R, G, B);
914 *udst++ = RGB2U(Ra, Ga, Ba);
915 *vdst++ = RGB2V(Ra, Ga, Ba);
921 return PRIMITIVES_SUCCESS;
924 static pstatus_t general_RGBToYUV420_8u_P3AC4R(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcFormat,
925 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst[3],
926 const UINT32 dstStep[3],
931 case PIXEL_FORMAT_BGRA32:
932 case PIXEL_FORMAT_BGRX32:
933 return general_RGBToYUV420_BGRX(pSrc, srcStep, pDst, dstStep, roi);
935 case PIXEL_FORMAT_RGBA32:
936 case PIXEL_FORMAT_RGBX32:
937 return general_RGBToYUV420_RGBX(pSrc, srcStep, pDst, dstStep, roi);
940 return general_RGBToYUV420_ANY(pSrc, srcFormat, srcStep, pDst, dstStep, roi);
944 static INLINE
void general_RGBToAVC444YUV_BGRX_DOUBLE_ROW(
945 const BYTE* WINPR_RESTRICT srcEven,
const BYTE* WINPR_RESTRICT srcOdd,
946 BYTE* WINPR_RESTRICT b1Even, BYTE* WINPR_RESTRICT b1Odd, BYTE* WINPR_RESTRICT b2,
947 BYTE* WINPR_RESTRICT b3, BYTE* WINPR_RESTRICT b4, BYTE* WINPR_RESTRICT b5,
948 BYTE* WINPR_RESTRICT b6, BYTE* WINPR_RESTRICT b7, UINT32 width)
950 for (UINT32 x = 0; x < width; x += 2)
952 const BOOL lastX = (x + 1) >= width;
967 const BYTE b = *srcEven++;
968 const BYTE g = *srcEven++;
969 const BYTE r = *srcEven++;
971 Y1e = Y2e = Y1o = Y2o = RGB2Y(r, g, b);
972 U1e = U2e = U1o = U2o = RGB2U(r, g, b);
973 V1e = V2e = V1o = V2o = RGB2V(r, g, b);
978 const BYTE b = *srcEven++;
979 const BYTE g = *srcEven++;
980 const BYTE r = *srcEven++;
982 Y2e = RGB2Y(r, g, b);
983 U2e = RGB2U(r, g, b);
984 V2e = RGB2V(r, g, b);
989 const BYTE b = *srcOdd++;
990 const BYTE g = *srcOdd++;
991 const BYTE r = *srcOdd++;
993 Y1o = Y2o = RGB2Y(r, g, b);
994 U1o = U2o = RGB2U(r, g, b);
995 V1o = V2o = RGB2V(r, g, b);
1000 const BYTE b = *srcOdd++;
1001 const BYTE g = *srcOdd++;
1002 const BYTE r = *srcOdd++;
1004 Y2o = RGB2Y(r, g, b);
1005 U2o = RGB2U(r, g, b);
1006 V2o = RGB2V(r, g, b);
1022 const BYTE Uavg = WINPR_ASSERTING_INT_CAST(BYTE, ((UINT16)U1e + U2e + U1o + U2o) / 4);
1023 const BYTE Vavg = WINPR_ASSERTING_INT_CAST(BYTE, ((UINT16)V1e + V2e + V1o + V2o) / 4);
1050 static INLINE pstatus_t general_RGBToAVC444YUV_BGRX(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcStep,
1051 BYTE* WINPR_RESTRICT pDst1[3],
1052 const UINT32 dst1Step[3],
1053 BYTE* WINPR_RESTRICT pDst2[3],
1054 const UINT32 dst2Step[3],
1061 const BYTE* pMaxSrc = pSrc + 1ULL * (roi->height - 1) * srcStep;
1063 for (UINT32 y = 0; y < roi->height; y += 2)
1065 const BOOL last = (y >= (roi->height - 1));
1066 const BYTE* srcEven = y < roi->height ? pSrc + 1ULL * y * srcStep : pMaxSrc;
1067 const BYTE* srcOdd = !last ? pSrc + 1ULL * (y + 1) * srcStep : pMaxSrc;
1068 const UINT32 i = y >> 1;
1069 const UINT32 n = (i & (uint32_t)~7) + i;
1070 BYTE* b1Even = pDst1[0] + 1ULL * y * dst1Step[0];
1071 BYTE* b1Odd = !last ? (b1Even + dst1Step[0]) : NULL;
1072 BYTE* b2 = pDst1[1] + 1ULL * (y / 2) * dst1Step[1];
1073 BYTE* b3 = pDst1[2] + 1ULL * (y / 2) * dst1Step[2];
1074 BYTE* b4 = pDst2[0] + 1ULL * dst2Step[0] * n;
1075 BYTE* b5 = b4 + 8ULL * dst2Step[0];
1076 BYTE* b6 = pDst2[1] + 1ULL * (y / 2) * dst2Step[1];
1077 BYTE* b7 = pDst2[2] + 1ULL * (y / 2) * dst2Step[2];
1078 general_RGBToAVC444YUV_BGRX_DOUBLE_ROW(srcEven, srcOdd, b1Even, b1Odd, b2, b3, b4, b5, b6,
1082 return PRIMITIVES_SUCCESS;
1085 static INLINE
void general_RGBToAVC444YUV_RGBX_DOUBLE_ROW(
1086 const BYTE* WINPR_RESTRICT srcEven,
const BYTE* WINPR_RESTRICT srcOdd,
1087 BYTE* WINPR_RESTRICT b1Even, BYTE* WINPR_RESTRICT b1Odd, BYTE* WINPR_RESTRICT b2,
1088 BYTE* WINPR_RESTRICT b3, BYTE* WINPR_RESTRICT b4, BYTE* WINPR_RESTRICT b5,
1089 BYTE* WINPR_RESTRICT b6, BYTE* WINPR_RESTRICT b7, UINT32 width)
1091 for (UINT32 x = 0; x < width; x += 2)
1093 const BOOL lastX = (x + 1) >= width;
1108 const BYTE r = *srcEven++;
1109 const BYTE g = *srcEven++;
1110 const BYTE b = *srcEven++;
1112 Y1e = Y2e = Y1o = Y2o = RGB2Y(r, g, b);
1113 U1e = U2e = U1o = U2o = RGB2U(r, g, b);
1114 V1e = V2e = V1o = V2o = RGB2V(r, g, b);
1119 const BYTE r = *srcEven++;
1120 const BYTE g = *srcEven++;
1121 const BYTE b = *srcEven++;
1123 Y2e = RGB2Y(r, g, b);
1124 U2e = RGB2U(r, g, b);
1125 V2e = RGB2V(r, g, b);
1130 const BYTE r = *srcOdd++;
1131 const BYTE g = *srcOdd++;
1132 const BYTE b = *srcOdd++;
1134 Y1o = Y2o = RGB2Y(r, g, b);
1135 U1o = U2o = RGB2U(r, g, b);
1136 V1o = V2o = RGB2V(r, g, b);
1139 if (b1Odd && !lastX)
1141 const BYTE r = *srcOdd++;
1142 const BYTE g = *srcOdd++;
1143 const BYTE b = *srcOdd++;
1145 Y2o = RGB2Y(r, g, b);
1146 U2o = RGB2U(r, g, b);
1147 V2o = RGB2V(r, g, b);
1163 const BYTE Uavg = WINPR_ASSERTING_INT_CAST(BYTE, ((UINT16)U1e + U2e + U1o + U2o) / 4);
1164 const BYTE Vavg = WINPR_ASSERTING_INT_CAST(BYTE, ((UINT16)V1e + V2e + V1o + V2o) / 4);
1191 static INLINE pstatus_t general_RGBToAVC444YUV_RGBX(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcStep,
1192 BYTE* WINPR_RESTRICT pDst1[3],
1193 const UINT32 dst1Step[3],
1194 BYTE* WINPR_RESTRICT pDst2[3],
1195 const UINT32 dst2Step[3],
1202 const BYTE* pMaxSrc = pSrc + 1ULL * (roi->height - 1) * srcStep;
1204 for (UINT32 y = 0; y < roi->height; y += 2)
1206 const BOOL last = (y >= (roi->height - 1));
1207 const BYTE* srcEven = y < roi->height ? pSrc + 1ULL * y * srcStep : pMaxSrc;
1208 const BYTE* srcOdd = !last ? pSrc + 1ULL * (y + 1) * srcStep : pMaxSrc;
1209 const UINT32 i = y >> 1;
1210 const UINT32 n = (i & (uint32_t)~7) + i;
1211 BYTE* b1Even = pDst1[0] + 1ULL * y * dst1Step[0];
1212 BYTE* b1Odd = !last ? (b1Even + dst1Step[0]) : NULL;
1213 BYTE* b2 = pDst1[1] + 1ULL * (y / 2) * dst1Step[1];
1214 BYTE* b3 = pDst1[2] + 1ULL * (y / 2) * dst1Step[2];
1215 BYTE* b4 = pDst2[0] + 1ULL * dst2Step[0] * n;
1216 BYTE* b5 = b4 + 8ULL * dst2Step[0];
1217 BYTE* b6 = pDst2[1] + 1ULL * (y / 2) * dst2Step[1];
1218 BYTE* b7 = pDst2[2] + 1ULL * (y / 2) * dst2Step[2];
1219 general_RGBToAVC444YUV_RGBX_DOUBLE_ROW(srcEven, srcOdd, b1Even, b1Odd, b2, b3, b4, b5, b6,
1223 return PRIMITIVES_SUCCESS;
1226 static INLINE
void general_RGBToAVC444YUV_ANY_DOUBLE_ROW(
1227 const BYTE* WINPR_RESTRICT srcEven,
const BYTE* WINPR_RESTRICT srcOdd, UINT32 srcFormat,
1228 BYTE* WINPR_RESTRICT b1Even, BYTE* WINPR_RESTRICT b1Odd, BYTE* WINPR_RESTRICT b2,
1229 BYTE* WINPR_RESTRICT b3, BYTE* WINPR_RESTRICT b4, BYTE* WINPR_RESTRICT b5,
1230 BYTE* WINPR_RESTRICT b6, BYTE* WINPR_RESTRICT b7, UINT32 width)
1232 const UINT32 bpp = FreeRDPGetBytesPerPixel(srcFormat);
1233 for (UINT32 x = 0; x < width; x += 2)
1235 const BOOL lastX = (x + 1) >= width;
1253 const UINT32 color = FreeRDPReadColor(srcEven, srcFormat);
1255 FreeRDPSplitColor(color, srcFormat, &r, &g, &b, NULL, NULL);
1256 Y1e = Y2e = Y1o = Y2o = RGB2Y(r, g, b);
1257 U1e = U2e = U1o = U2o = RGB2U(r, g, b);
1258 V1e = V2e = V1o = V2o = RGB2V(r, g, b);
1266 const UINT32 color = FreeRDPReadColor(srcEven, srcFormat);
1268 FreeRDPSplitColor(color, srcFormat, &r, &g, &b, NULL, NULL);
1269 Y2e = RGB2Y(r, g, b);
1270 U2e = RGB2U(r, g, b);
1271 V2e = RGB2V(r, g, b);
1279 const UINT32 color = FreeRDPReadColor(srcOdd, srcFormat);
1281 FreeRDPSplitColor(color, srcFormat, &r, &g, &b, NULL, NULL);
1282 Y1o = Y2o = RGB2Y(r, g, b);
1283 U1o = U2o = RGB2U(r, g, b);
1284 V1o = V2o = RGB2V(r, g, b);
1287 if (b1Odd && !lastX)
1292 const UINT32 color = FreeRDPReadColor(srcOdd, srcFormat);
1294 FreeRDPSplitColor(color, srcFormat, &r, &g, &b, NULL, NULL);
1295 Y2o = RGB2Y(r, g, b);
1296 U2o = RGB2U(r, g, b);
1297 V2o = RGB2V(r, g, b);
1313 const BYTE Uavg = WINPR_ASSERTING_INT_CAST(
1314 BYTE, ((UINT16)U1e + (UINT16)U2e + (UINT16)U1o + (UINT16)U2o) / 4);
1315 const BYTE Vavg = WINPR_ASSERTING_INT_CAST(
1316 BYTE, ((UINT16)V1e + (UINT16)V2e + (UINT16)V1o + (UINT16)V2o) / 4);
1343 static INLINE pstatus_t general_RGBToAVC444YUV_ANY(
1344 const BYTE* WINPR_RESTRICT pSrc, UINT32 srcFormat, UINT32 srcStep,
1345 BYTE* WINPR_RESTRICT pDst1[3],
const UINT32 dst1Step[3], BYTE* WINPR_RESTRICT pDst2[3],
1346 const UINT32 dst2Step[3],
const prim_size_t* WINPR_RESTRICT roi)
1405 const BYTE* pMaxSrc = pSrc + 1ULL * (roi->height - 1) * srcStep;
1407 for (
size_t y = 0; y < roi->height; y += 2)
1409 WINPR_ASSERT(y < UINT32_MAX);
1411 const BOOL last = (y >= (roi->height - 1));
1412 const BYTE* srcEven = y < roi->height ? pSrc + y * srcStep : pMaxSrc;
1413 const BYTE* srcOdd = !last ? pSrc + (y + 1) * srcStep : pMaxSrc;
1414 const UINT32 i = (UINT32)y >> 1;
1415 const UINT32 n = (i & (uint32_t)~7) + i;
1416 BYTE* b1Even = pDst1[0] + y * dst1Step[0];
1417 BYTE* b1Odd = !last ? (b1Even + dst1Step[0]) : NULL;
1418 BYTE* b2 = pDst1[1] + (y / 2) * dst1Step[1];
1419 BYTE* b3 = pDst1[2] + (y / 2) * dst1Step[2];
1420 BYTE* b4 = pDst2[0] + 1ULL * dst2Step[0] * n;
1421 BYTE* b5 = b4 + 8ULL * dst2Step[0];
1422 BYTE* b6 = pDst2[1] + (y / 2) * dst2Step[1];
1423 BYTE* b7 = pDst2[2] + (y / 2) * dst2Step[2];
1424 general_RGBToAVC444YUV_ANY_DOUBLE_ROW(srcEven, srcOdd, srcFormat, b1Even, b1Odd, b2, b3, b4,
1425 b5, b6, b7, roi->width);
1428 return PRIMITIVES_SUCCESS;
1431 static INLINE pstatus_t general_RGBToAVC444YUV(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcFormat,
1432 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst1[3],
1433 const UINT32 dst1Step[3],
1434 BYTE* WINPR_RESTRICT pDst2[3],
1435 const UINT32 dst2Step[3],
1438 if (!pSrc || !pDst1 || !dst1Step || !pDst2 || !dst2Step)
1441 if (!pDst1[0] || !pDst1[1] || !pDst1[2])
1444 if (!dst1Step[0] || !dst1Step[1] || !dst1Step[2])
1447 if (!pDst2[0] || !pDst2[1] || !pDst2[2])
1450 if (!dst2Step[0] || !dst2Step[1] || !dst2Step[2])
1455 case PIXEL_FORMAT_BGRA32:
1456 case PIXEL_FORMAT_BGRX32:
1457 return general_RGBToAVC444YUV_BGRX(pSrc, srcStep, pDst1, dst1Step, pDst2, dst2Step,
1460 case PIXEL_FORMAT_RGBA32:
1461 case PIXEL_FORMAT_RGBX32:
1462 return general_RGBToAVC444YUV_RGBX(pSrc, srcStep, pDst1, dst1Step, pDst2, dst2Step,
1466 return general_RGBToAVC444YUV_ANY(pSrc, srcFormat, srcStep, pDst1, dst1Step, pDst2,
1470 return !PRIMITIVES_SUCCESS;
1473 static INLINE
void general_RGBToAVC444YUVv2_ANY_DOUBLE_ROW(
1474 const BYTE* WINPR_RESTRICT srcEven,
const BYTE* WINPR_RESTRICT srcOdd, UINT32 srcFormat,
1475 BYTE* WINPR_RESTRICT yLumaDstEven, BYTE* WINPR_RESTRICT yLumaDstOdd,
1476 BYTE* WINPR_RESTRICT uLumaDst, BYTE* WINPR_RESTRICT vLumaDst,
1477 BYTE* WINPR_RESTRICT yEvenChromaDst1, BYTE* WINPR_RESTRICT yEvenChromaDst2,
1478 BYTE* WINPR_RESTRICT yOddChromaDst1, BYTE* WINPR_RESTRICT yOddChromaDst2,
1479 BYTE* WINPR_RESTRICT uChromaDst1, BYTE* WINPR_RESTRICT uChromaDst2,
1480 BYTE* WINPR_RESTRICT vChromaDst1, BYTE* WINPR_RESTRICT vChromaDst2, UINT32 width)
1482 const UINT32 bpp = FreeRDPGetBytesPerPixel(srcFormat);
1484 for (UINT32 x = 0; x < width; x += 2)
1502 const UINT32 color = FreeRDPReadColor(srcEven, srcFormat);
1504 FreeRDPSplitColor(color, srcFormat, &r, &g, &b, NULL, NULL);
1505 Ya = RGB2Y(r, g, b);
1506 Ua = RGB2U(r, g, b);
1507 Va = RGB2V(r, g, b);
1515 const UINT32 color = FreeRDPReadColor(srcEven, srcFormat);
1517 FreeRDPSplitColor(color, srcFormat, &r, &g, &b, NULL, NULL);
1518 Yb = RGB2Y(r, g, b);
1519 Ub = RGB2U(r, g, b);
1520 Vb = RGB2V(r, g, b);
1534 const UINT32 color = FreeRDPReadColor(srcOdd, srcFormat);
1536 FreeRDPSplitColor(color, srcFormat, &r, &g, &b, NULL, NULL);
1537 Yc = RGB2Y(r, g, b);
1538 Uc = RGB2U(r, g, b);
1539 Vc = RGB2V(r, g, b);
1548 if (srcOdd && (x < width - 1))
1553 const UINT32 color = FreeRDPReadColor(srcOdd, srcFormat);
1555 FreeRDPSplitColor(color, srcFormat, &r, &g, &b, NULL, NULL);
1556 Yd = RGB2Y(r, g, b);
1557 Ud = RGB2U(r, g, b);
1558 Vd = RGB2V(r, g, b);
1568 *yLumaDstEven++ = Ya;
1571 *yLumaDstEven++ = Yb;
1574 *yLumaDstOdd++ = Yc;
1576 if (srcOdd && (x < width - 1))
1577 *yLumaDstOdd++ = Yd;
1580 *uLumaDst++ = (Ua + Ub + Uc + Ud) / 4;
1581 *vLumaDst++ = (Va + Vb + Vc + Vd) / 4;
1586 *yEvenChromaDst1++ = Ub;
1587 *yEvenChromaDst2++ = Vb;
1595 *yOddChromaDst1++ = Ud;
1596 *yOddChromaDst2++ = Vd;
1602 *uChromaDst1++ = Uc;
1603 *uChromaDst2++ = Vc;
1608 *vChromaDst1++ = Uc;
1609 *vChromaDst2++ = Vc;
1615 static INLINE pstatus_t general_RGBToAVC444YUVv2_ANY(
1616 const BYTE* WINPR_RESTRICT pSrc, UINT32 srcFormat, UINT32 srcStep,
1617 BYTE* WINPR_RESTRICT pDst1[3],
const UINT32 dst1Step[3], BYTE* WINPR_RESTRICT pDst2[3],
1618 const UINT32 dst2Step[3],
const prim_size_t* WINPR_RESTRICT roi)
1670 if (roi->height < 1 || roi->width < 1)
1671 return !PRIMITIVES_SUCCESS;
1673 for (
size_t y = 0; y < roi->height; y += 2)
1675 const BYTE* srcEven = (pSrc + y * srcStep);
1676 const BYTE* srcOdd = (y < roi->height - 1) ? (srcEven + srcStep) : NULL;
1677 BYTE* dstLumaYEven = (pDst1[0] + y * dst1Step[0]);
1678 BYTE* dstLumaYOdd = (dstLumaYEven + dst1Step[0]);
1679 BYTE* dstLumaU = (pDst1[1] + (y / 2) * dst1Step[1]);
1680 BYTE* dstLumaV = (pDst1[2] + (y / 2) * dst1Step[2]);
1681 BYTE* dstEvenChromaY1 = (pDst2[0] + y * dst2Step[0]);
1682 BYTE* dstEvenChromaY2 = dstEvenChromaY1 + roi->width / 2;
1683 BYTE* dstOddChromaY1 = dstEvenChromaY1 + dst2Step[0];
1684 BYTE* dstOddChromaY2 = dstEvenChromaY2 + dst2Step[0];
1685 BYTE* dstChromaU1 = (pDst2[1] + (y / 2) * dst2Step[1]);
1686 BYTE* dstChromaV1 = (pDst2[2] + (y / 2) * dst2Step[2]);
1687 BYTE* dstChromaU2 = dstChromaU1 + roi->width / 4;
1688 BYTE* dstChromaV2 = dstChromaV1 + roi->width / 4;
1689 general_RGBToAVC444YUVv2_ANY_DOUBLE_ROW(
1690 srcEven, srcOdd, srcFormat, dstLumaYEven, dstLumaYOdd, dstLumaU, dstLumaV,
1691 dstEvenChromaY1, dstEvenChromaY2, dstOddChromaY1, dstOddChromaY2, dstChromaU1,
1692 dstChromaU2, dstChromaV1, dstChromaV2, roi->width);
1695 return PRIMITIVES_SUCCESS;
1698 static INLINE
void general_RGBToAVC444YUVv2_BGRX_DOUBLE_ROW(
1699 const BYTE* WINPR_RESTRICT srcEven,
const BYTE* WINPR_RESTRICT srcOdd,
1700 BYTE* WINPR_RESTRICT yLumaDstEven, BYTE* WINPR_RESTRICT yLumaDstOdd,
1701 BYTE* WINPR_RESTRICT uLumaDst, BYTE* WINPR_RESTRICT vLumaDst,
1702 BYTE* WINPR_RESTRICT yEvenChromaDst1, BYTE* WINPR_RESTRICT yEvenChromaDst2,
1703 BYTE* WINPR_RESTRICT yOddChromaDst1, BYTE* WINPR_RESTRICT yOddChromaDst2,
1704 BYTE* WINPR_RESTRICT uChromaDst1, BYTE* WINPR_RESTRICT uChromaDst2,
1705 BYTE* WINPR_RESTRICT vChromaDst1, BYTE* WINPR_RESTRICT vChromaDst2, UINT32 width)
1707 for (UINT32 x = 0; x < width; x += 2)
1722 const BYTE b = *srcEven++;
1723 const BYTE g = *srcEven++;
1724 const BYTE r = *srcEven++;
1726 Ya = RGB2Y(r, g, b);
1727 Ua = RGB2U(r, g, b);
1728 Va = RGB2V(r, g, b);
1733 const BYTE b = *srcEven++;
1734 const BYTE g = *srcEven++;
1735 const BYTE r = *srcEven++;
1737 Yb = RGB2Y(r, g, b);
1738 Ub = RGB2U(r, g, b);
1739 Vb = RGB2V(r, g, b);
1750 const BYTE b = *srcOdd++;
1751 const BYTE g = *srcOdd++;
1752 const BYTE r = *srcOdd++;
1754 Yc = RGB2Y(r, g, b);
1755 Uc = RGB2U(r, g, b);
1756 Vc = RGB2V(r, g, b);
1765 if (srcOdd && (x < width - 1))
1767 const BYTE b = *srcOdd++;
1768 const BYTE g = *srcOdd++;
1769 const BYTE r = *srcOdd++;
1771 Yd = RGB2Y(r, g, b);
1772 Ud = RGB2U(r, g, b);
1773 Vd = RGB2V(r, g, b);
1783 *yLumaDstEven++ = Ya;
1786 *yLumaDstEven++ = Yb;
1789 *yLumaDstOdd++ = Yc;
1791 if (srcOdd && (x < width - 1))
1792 *yLumaDstOdd++ = Yd;
1795 *uLumaDst++ = (Ua + Ub + Uc + Ud) / 4;
1796 *vLumaDst++ = (Va + Vb + Vc + Vd) / 4;
1801 *yEvenChromaDst1++ = Ub;
1802 *yEvenChromaDst2++ = Vb;
1810 *yOddChromaDst1++ = Ud;
1811 *yOddChromaDst2++ = Vd;
1817 *uChromaDst1++ = Uc;
1818 *uChromaDst2++ = Vc;
1823 *vChromaDst1++ = Uc;
1824 *vChromaDst2++ = Vc;
1830 static INLINE pstatus_t general_RGBToAVC444YUVv2_BGRX(
const BYTE* WINPR_RESTRICT pSrc,
1831 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst1[3],
1832 const UINT32 dst1Step[3],
1833 BYTE* WINPR_RESTRICT pDst2[3],
1834 const UINT32 dst2Step[3],
1837 if (roi->height < 1 || roi->width < 1)
1838 return !PRIMITIVES_SUCCESS;
1840 for (
size_t y = 0; y < roi->height; y += 2)
1842 const BYTE* srcEven = (pSrc + y * srcStep);
1843 const BYTE* srcOdd = (y < roi->height - 1) ? (srcEven + srcStep) : NULL;
1844 BYTE* dstLumaYEven = (pDst1[0] + y * dst1Step[0]);
1845 BYTE* dstLumaYOdd = (dstLumaYEven + dst1Step[0]);
1846 BYTE* dstLumaU = (pDst1[1] + (y / 2) * dst1Step[1]);
1847 BYTE* dstLumaV = (pDst1[2] + (y / 2) * dst1Step[2]);
1848 BYTE* dstEvenChromaY1 = (pDst2[0] + y * dst2Step[0]);
1849 BYTE* dstEvenChromaY2 = dstEvenChromaY1 + roi->width / 2;
1850 BYTE* dstOddChromaY1 = dstEvenChromaY1 + dst2Step[0];
1851 BYTE* dstOddChromaY2 = dstEvenChromaY2 + dst2Step[0];
1852 BYTE* dstChromaU1 = (pDst2[1] + (y / 2) * dst2Step[1]);
1853 BYTE* dstChromaV1 = (pDst2[2] + (y / 2) * dst2Step[2]);
1854 BYTE* dstChromaU2 = dstChromaU1 + roi->width / 4;
1855 BYTE* dstChromaV2 = dstChromaV1 + roi->width / 4;
1856 general_RGBToAVC444YUVv2_BGRX_DOUBLE_ROW(
1857 srcEven, srcOdd, dstLumaYEven, dstLumaYOdd, dstLumaU, dstLumaV, dstEvenChromaY1,
1858 dstEvenChromaY2, dstOddChromaY1, dstOddChromaY2, dstChromaU1, dstChromaU2, dstChromaV1,
1859 dstChromaV2, roi->width);
1862 return PRIMITIVES_SUCCESS;
1865 static INLINE pstatus_t general_RGBToAVC444YUVv2(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcFormat,
1866 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst1[3],
1867 const UINT32 dst1Step[3],
1868 BYTE* WINPR_RESTRICT pDst2[3],
1869 const UINT32 dst2Step[3],
1874 case PIXEL_FORMAT_BGRA32:
1875 case PIXEL_FORMAT_BGRX32:
1876 return general_RGBToAVC444YUVv2_BGRX(pSrc, srcStep, pDst1, dst1Step, pDst2, dst2Step,
1880 return general_RGBToAVC444YUVv2_ANY(pSrc, srcFormat, srcStep, pDst1, dst1Step, pDst2,
1884 return !PRIMITIVES_SUCCESS;
1887 void primitives_init_YUV(
primitives_t* WINPR_RESTRICT prims)
1889 prims->YUV420ToRGB_8u_P3AC4R = general_YUV420ToRGB_8u_P3AC4R;
1890 prims->YUV444ToRGB_8u_P3AC4R = general_YUV444ToRGB_8u_P3AC4R;
1891 prims->RGBToYUV420_8u_P3AC4R = general_RGBToYUV420_8u_P3AC4R;
1892 prims->RGBToYUV444_8u_P3AC4R = general_RGBToYUV444_8u_P3AC4R;
1893 prims->YUV420CombineToYUV444 = general_YUV420CombineToYUV444;
1894 prims->YUV444SplitToYUV420 = general_YUV444SplitToYUV420;
1895 prims->RGBToAVC444YUV = general_RGBToAVC444YUV;
1896 prims->RGBToAVC444YUVv2 = general_RGBToAVC444YUVv2;
1899 void primitives_init_YUV_opt(
primitives_t* WINPR_RESTRICT prims)
1901 primitives_init_YUV_ssse3(prims);
1902 primitives_init_YUV_neon(prims);