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"
36static inline pstatus_t general_LumaToYUV444(
const BYTE* WINPR_RESTRICT pSrcRaw[3],
37 const UINT32 srcStep[3],
38 BYTE* WINPR_RESTRICT pDstRaw[3],
39 const UINT32 dstStep[3],
42 const UINT32 nWidth = roi->right - roi->left;
43 const UINT32 nHeight = roi->bottom - roi->top;
44 const UINT32 halfWidth = (nWidth + 1) / 2;
45 const UINT32 halfHeight = (nHeight + 1) / 2;
46 const UINT32 oddY = 1;
47 const UINT32 evenY = 0;
48 const UINT32 oddX = 1;
49 const UINT32 evenX = 0;
50 const BYTE* pSrc[3] = { pSrcRaw[0] + 1ULL * roi->top * srcStep[0] + roi->left,
51 pSrcRaw[1] + 1ULL * roi->top / 2 * srcStep[1] + roi->left / 2,
52 pSrcRaw[2] + 1ULL * roi->top / 2 * srcStep[2] + roi->left / 2 };
53 BYTE* pDst[3] = { pDstRaw[0] + 1ULL * roi->top * dstStep[0] + roi->left,
54 pDstRaw[1] + 1ULL * roi->top * dstStep[1] + roi->left,
55 pDstRaw[2] + 1ULL * roi->top * dstStep[2] + roi->left };
59 for (
size_t y = 0; y < nHeight; y++)
61 const BYTE* Ym = pSrc[0] + y * srcStep[0];
62 BYTE* pY = pDst[0] + dstStep[0] * y;
63 memcpy(pY, Ym, nWidth);
68 for (UINT32 y = 0; y < halfHeight; y++)
70 const UINT32 val2y = (2UL * y + evenY);
71 const UINT32 val2y1 = val2y + oddY;
72 const BYTE* Um = pSrc[1] + 1ULL * y * srcStep[1];
73 const BYTE* Vm = pSrc[2] + 1ULL * y * srcStep[2];
74 BYTE* pU = pDst[1] + 1ULL * dstStep[1] * val2y;
75 BYTE* pV = pDst[2] + 1ULL * dstStep[2] * val2y;
76 BYTE* pU1 = pDst[1] + 1ULL * dstStep[1] * val2y1;
77 BYTE* pV1 = pDst[2] + 1ULL * dstStep[2] * val2y1;
79 for (UINT32 x = 0; x < halfWidth; x++)
81 const UINT32 val2x = 2UL * x + evenX;
82 const UINT32 val2x1 = val2x + oddX;
94 return PRIMITIVES_SUCCESS;
97static inline pstatus_t general_ChromaV1ToYUV444(
const BYTE* WINPR_RESTRICT pSrcRaw[3],
98 const UINT32 srcStep[3],
99 BYTE* WINPR_RESTRICT pDstRaw[3],
100 const UINT32 dstStep[3],
103 const UINT32 mod = 16;
106 const UINT32 nWidth = roi->right - roi->left;
107 const UINT32 nHeight = roi->bottom - roi->top;
108 const UINT32 halfWidth = (nWidth) / 2;
109 const UINT32 halfHeight = (nHeight) / 2;
110 const UINT32 oddY = 1;
111 const UINT32 evenY = 0;
112 const UINT32 oddX = 1;
115 const UINT32 padHeight = nHeight + 16 - nHeight % 16;
116 const BYTE* pSrc[3] = { pSrcRaw[0] + 1ULL * roi->top * srcStep[0] + roi->left,
117 pSrcRaw[1] + 1ULL * roi->top / 2 * srcStep[1] + roi->left / 2,
118 pSrcRaw[2] + 1ULL * roi->top / 2 * srcStep[2] + roi->left / 2 };
119 BYTE* pDst[3] = { pDstRaw[0] + 1ULL * roi->top * dstStep[0] + roi->left,
120 pDstRaw[1] + 1ULL * roi->top * dstStep[1] + roi->left,
121 pDstRaw[2] + 1ULL * roi->top * dstStep[2] + roi->left };
125 for (
size_t y = 0; y < padHeight; y++)
127 const BYTE* Ya = pSrc[0] + y * srcStep[0];
130 if ((y) % mod < (mod + 1) / 2)
132 const size_t pos = (2 * uY++ + oddY);
137 pX = pDst[1] + dstStep[1] * pos;
141 const size_t pos = (2 * vY++ + oddY);
146 pX = pDst[2] + dstStep[2] * pos;
150 memcpy(pX, Ya, nWidth);
154 for (UINT32 y = 0; y < halfHeight; y++)
156 const UINT32 val2y = (y * 2UL + evenY);
157 const BYTE* Ua = pSrc[1] + 1ULL * y * srcStep[1];
158 const BYTE* Va = pSrc[2] + 1ULL * y * srcStep[2];
159 BYTE* pU = pDst[1] + 1ULL * dstStep[1] * val2y;
160 BYTE* pV = pDst[2] + 1ULL * dstStep[2] * val2y;
162 for (UINT32 x = 0; x < halfWidth; x++)
164 const UINT32 val2x1 = (x * 2 + oddX);
170 return PRIMITIVES_SUCCESS;
173static inline pstatus_t general_ChromaV2ToYUV444(
const BYTE* WINPR_RESTRICT pSrc[3],
174 const UINT32 srcStep[3], UINT32 nTotalWidth,
175 WINPR_ATTR_UNUSED UINT32 nTotalHeight,
176 BYTE* WINPR_RESTRICT pDst[3],
177 const UINT32 dstStep[3],
180 const UINT32 nWidth = roi->right - roi->left;
181 const UINT32 nHeight = roi->bottom - roi->top;
182 const UINT32 halfWidth = (nWidth + 1) / 2;
183 const UINT32 halfHeight = (nHeight + 1) / 2;
184 const UINT32 quaterWidth = (nWidth + 3) / 4;
187 for (UINT32 y = 0; y < nHeight; y++)
189 const UINT32 yTop = y + roi->top;
190 const BYTE* pYaU = pSrc[0] + 1ULL * srcStep[0] * yTop + roi->left / 2;
191 const BYTE* pYaV = pYaU + nTotalWidth / 2;
192 BYTE* pU = pDst[1] + 1ULL * dstStep[1] * yTop + roi->left;
193 BYTE* pV = pDst[2] + 1ULL * dstStep[2] * yTop + roi->left;
195 for (UINT32 x = 0; x < halfWidth; x++)
197 const UINT32 odd = 2UL * x + 1UL;
204 for (
size_t y = 0; y < halfHeight; y++)
206 const BYTE* pUaU = pSrc[1] + srcStep[1] * (y + roi->top / 2) + roi->left / 4;
207 const BYTE* pUaV = pUaU + nTotalWidth / 4;
208 const BYTE* pVaU = pSrc[2] + srcStep[2] * (y + roi->top / 2) + roi->left / 4;
209 const BYTE* pVaV = pVaU + nTotalWidth / 4;
210 BYTE* pU = pDst[1] + 1ULL * dstStep[1] * (2ULL * y + 1 + roi->top) + roi->left;
211 BYTE* pV = pDst[2] + 1ULL * dstStep[2] * (2ULL * y + 1 + roi->top) + roi->left;
213 for (
size_t x = 0; x < quaterWidth; x++)
215 pU[4 * x + 0] = *pUaU++;
216 pV[4 * x + 0] = *pUaV++;
217 pU[4 * x + 2] = *pVaU++;
218 pV[4 * x + 2] = *pVaV++;
222 return PRIMITIVES_SUCCESS;
225static pstatus_t general_YUV420CombineToYUV444(avc444_frame_type type,
226 const BYTE* WINPR_RESTRICT pSrc[3],
227 const UINT32 srcStep[3], UINT32 nWidth,
228 UINT32 nHeight, BYTE* WINPR_RESTRICT pDst[3],
229 const UINT32 dstStep[3],
232 if (!pSrc || !pSrc[0] || !pSrc[1] || !pSrc[2])
235 if (!pDst || !pDst[0] || !pDst[1] || !pDst[2])
244 return general_LumaToYUV444(pSrc, srcStep, pDst, dstStep, roi);
246 case AVC444_CHROMAv1:
247 return general_ChromaV1ToYUV444(pSrc, srcStep, pDst, dstStep, roi);
249 case AVC444_CHROMAv2:
250 return general_ChromaV2ToYUV444(pSrc, srcStep, nWidth, nHeight, pDst, dstStep, roi);
258general_YUV444SplitToYUV420(
const BYTE* WINPR_RESTRICT pSrc[3],
const UINT32 srcStep[3],
259 BYTE* WINPR_RESTRICT pMainDst[3],
const UINT32 dstMainStep[3],
260 BYTE* WINPR_RESTRICT pAuxDst[3],
const UINT32 dstAuxStep[3],
268 const UINT32 padHeight = roi->height + 16 - roi->height % 16;
269 const UINT32 halfWidth = (roi->width + 1) / 2;
270 const UINT32 halfHeight = (roi->height + 1) / 2;
273 for (
size_t y = 0; y < roi->height; y++)
275 const BYTE* pSrcY = pSrc[0] + y * srcStep[0];
276 BYTE* pY = pMainDst[0] + y * dstMainStep[0];
277 memcpy(pY, pSrcY, roi->width);
281 for (
size_t y = 0; y < halfHeight; y++)
283 const BYTE* pSrcU = pSrc[1] + 2ULL * y * srcStep[1];
284 const BYTE* pSrcV = pSrc[2] + 2ULL * y * srcStep[2];
285 BYTE* pU = pMainDst[1] + y * dstMainStep[1];
286 BYTE* pV = pMainDst[2] + y * dstMainStep[2];
288 for (
size_t x = 0; x < halfWidth; x++)
290 pU[x] = pSrcV[2 * x];
291 pV[x] = pSrcU[2 * x];
296 for (
size_t y = 0; y < padHeight; y++)
298 BYTE* pY = pAuxDst[0] + y * dstAuxStep[0];
302 const size_t pos = (2 * uY++ + 1);
303 const BYTE* pSrcU = pSrc[1] + pos * srcStep[1];
305 if (pos >= roi->height)
308 memcpy(pY, pSrcU, roi->width);
312 const size_t pos = (2 * vY++ + 1);
313 const BYTE* pSrcV = pSrc[2] + pos * srcStep[2];
315 if (pos >= roi->height)
318 memcpy(pY, pSrcV, roi->width);
323 for (
size_t y = 0; y < halfHeight; y++)
325 const BYTE* pSrcU = pSrc[1] + 2 * y * srcStep[1];
326 const BYTE* pSrcV = pSrc[2] + 2 * y * srcStep[2];
327 BYTE* pU = pAuxDst[1] + y * dstAuxStep[1];
328 BYTE* pV = pAuxDst[2] + y * dstAuxStep[2];
330 for (
size_t x = 0; x < halfWidth; x++)
332 pU[x] = pSrcU[2 * x + 1];
333 pV[x] = pSrcV[2 * x + 1];
337 return PRIMITIVES_SUCCESS;
340static inline void general_YUV444ToRGB_DOUBLE_ROW(BYTE* WINPR_RESTRICT pRGB[2], UINT32 DstFormat,
341 const BYTE* WINPR_RESTRICT pY[2],
342 const BYTE* WINPR_RESTRICT pU[2],
343 const BYTE* WINPR_RESTRICT pV[2],
size_t nWidth)
345 fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, FALSE);
347 for (
size_t x = 0; x < nWidth; x += 2)
349 for (
size_t i = 0; i < 2; i++)
351 for (
size_t j = 0; j < 2; j++)
353 const BYTE y = pY[i][x + j];
354 INT32 u = pU[i][x + j];
355 INT32 v = pV[i][x + j];
356 if ((i == 0) && (j == 0))
358 const INT32 subU = (INT32)pU[0][x + 1] + pU[1][x] + pU[1][x + 1];
359 const INT32 avgU = ((4 * u) - subU);
360 u = CONDITIONAL_CLIP(avgU, WINPR_ASSERTING_INT_CAST(BYTE, u));
362 const INT32 subV = (INT32)pV[0][x + 1] + pV[1][x] + pV[1][x + 1];
363 const INT32 avgV = ((4 * v) - subV);
364 v = CONDITIONAL_CLIP(avgV, WINPR_ASSERTING_INT_CAST(BYTE, v));
366 pRGB[i] = writeYUVPixel(pRGB[i], DstFormat, y, u, v, writePixel);
372static inline void general_YUV444ToRGB_SINGLE_ROW(BYTE* WINPR_RESTRICT pRGB, UINT32 DstFormat,
373 const BYTE* WINPR_RESTRICT pY,
374 const BYTE* WINPR_RESTRICT pU,
375 const BYTE* WINPR_RESTRICT pV,
size_t nWidth)
377 fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, FALSE);
379 for (
size_t x = 0; x < nWidth; x += 2)
381 for (
size_t j = 0; j < 2; j++)
383 const BYTE y = pY[x + j];
384 const BYTE u = pU[x + j];
385 const BYTE v = pV[x + j];
386 pRGB = writeYUVPixel(pRGB, DstFormat, y, u, v, writePixel);
391static inline pstatus_t general_YUV444ToRGB_8u_P3AC4R_general(
const BYTE* WINPR_RESTRICT pSrc[3],
392 const UINT32 srcStep[3],
393 BYTE* WINPR_RESTRICT pDst,
394 UINT32 dstStep, UINT32 DstFormat,
401 const UINT32 nWidth = roi->width;
402 const UINT32 nHeight = roi->height;
405 for (; y < nHeight - nHeight % 2; y += 2)
407 const BYTE* WINPR_RESTRICT pY[2] = { pSrc[0] + y * srcStep[0],
408 pSrc[0] + (y + 1) * srcStep[0] };
409 const BYTE* WINPR_RESTRICT pU[2] = { pSrc[1] + y * srcStep[1],
410 pSrc[1] + (y + 1) * srcStep[1] };
411 const BYTE* WINPR_RESTRICT pV[2] = { pSrc[2] + y * srcStep[2],
412 pSrc[2] + (y + 1) * srcStep[2] };
413 BYTE* WINPR_RESTRICT pRGB[] = { pDst + y * dstStep, pDst + (y + 1) * dstStep };
415 general_YUV444ToRGB_DOUBLE_ROW(pRGB, DstFormat, pY, pU, pV, nWidth);
417 for (; y < nHeight; y++)
419 const BYTE* WINPR_RESTRICT pY = pSrc[0] + y * srcStep[0];
420 const BYTE* WINPR_RESTRICT pU = pSrc[1] + y * srcStep[1];
421 const BYTE* WINPR_RESTRICT pV = pSrc[2] + y * srcStep[2];
422 BYTE* WINPR_RESTRICT pRGB = pDst + y * dstStep;
424 general_YUV444ToRGB_SINGLE_ROW(pRGB, DstFormat, pY, pU, pV, nWidth);
427 return PRIMITIVES_SUCCESS;
430static inline void general_YUV444ToBGRX_DOUBLE_ROW(BYTE* WINPR_RESTRICT pRGB[2], UINT32 DstFormat,
431 const BYTE* WINPR_RESTRICT pY[2],
432 const BYTE* WINPR_RESTRICT pU[2],
433 const BYTE* WINPR_RESTRICT pV[2],
size_t nWidth)
435 WINPR_ASSERT(nWidth % 2 == 0);
436 for (
size_t x = 0; x < nWidth; x += 2)
438 const INT32 subU = pU[0][x + 1] + pU[1][x] + pU[1][x + 1];
439 const INT32 avgU = ((4 * pU[0][x]) - subU);
440 const BYTE useU = CONDITIONAL_CLIP(avgU, pU[0][x]);
441 const INT32 subV = pV[0][x + 1] + pV[1][x] + pV[1][x + 1];
442 const INT32 avgV = ((4 * pV[0][x]) - subV);
443 const BYTE useV = CONDITIONAL_CLIP(avgV, pV[0][x]);
445 const BYTE U[2][2] = { { useU, pU[0][x + 1] }, { pU[1][x], pU[1][x + 1] } };
446 const BYTE V[2][2] = { { useV, pV[0][x + 1] }, { pV[1][x], pV[1][x + 1] } };
448 for (
size_t i = 0; i < 2; i++)
450 for (
size_t j = 0; j < 2; j++)
452 const BYTE y = pY[i][x + j];
453 const BYTE u = U[i][j];
454 const BYTE v = V[i][j];
455 pRGB[i] = writeYUVPixel(pRGB[i], DstFormat, y, u, v, writePixelBGRX);
461static inline void general_YUV444ToBGRX_SINGLE_ROW(BYTE* WINPR_RESTRICT pRGB, UINT32 DstFormat,
462 const BYTE* WINPR_RESTRICT pY,
463 const BYTE* WINPR_RESTRICT pU,
464 const BYTE* WINPR_RESTRICT pV,
size_t nWidth)
466 WINPR_ASSERT(nWidth % 2 == 0);
467 for (
size_t x = 0; x < nWidth; x += 2)
469 for (
size_t j = 0; j < 2; j++)
471 const BYTE Y = pY[x + j];
472 const BYTE U = pU[x + j];
473 const BYTE V = pV[x + j];
474 pRGB = writeYUVPixel(pRGB, DstFormat, Y, U, V, writePixelBGRX);
479static inline pstatus_t general_YUV444ToRGB_8u_P3AC4R_BGRX(
const BYTE* WINPR_RESTRICT pSrc[3],
480 const UINT32 srcStep[3],
481 BYTE* WINPR_RESTRICT pDst,
482 UINT32 dstStep, UINT32 DstFormat,
489 const UINT32 nWidth = roi->width;
490 const UINT32 nHeight = roi->height;
493 for (; y < nHeight - nHeight % 2; y += 2)
495 const BYTE* pY[2] = { pSrc[0] + y * srcStep[0], pSrc[0] + (y + 1) * srcStep[0] };
496 const BYTE* pU[2] = { pSrc[1] + y * srcStep[1], pSrc[1] + (y + 1) * srcStep[1] };
497 const BYTE* pV[2] = { pSrc[2] + y * srcStep[2], pSrc[2] + (y + 1) * srcStep[2] };
498 BYTE* pRGB[] = { pDst + y * dstStep, pDst + (y + 1) * dstStep };
500 general_YUV444ToBGRX_DOUBLE_ROW(pRGB, DstFormat, pY, pU, pV, nWidth);
503 for (; y < nHeight; y++)
505 const BYTE* WINPR_RESTRICT pY = pSrc[0] + y * srcStep[0];
506 const BYTE* WINPR_RESTRICT pU = pSrc[1] + y * srcStep[1];
507 const BYTE* WINPR_RESTRICT pV = pSrc[2] + y * srcStep[2];
508 BYTE* WINPR_RESTRICT pRGB = pDst + y * dstStep;
510 general_YUV444ToBGRX_SINGLE_ROW(pRGB, DstFormat, pY, pU, pV, nWidth);
512 return PRIMITIVES_SUCCESS;
515static pstatus_t general_YUV444ToRGB_8u_P3AC4R(
const BYTE* WINPR_RESTRICT pSrc[3],
516 const UINT32 srcStep[3], BYTE* WINPR_RESTRICT pDst,
517 UINT32 dstStep, UINT32 DstFormat,
522 case PIXEL_FORMAT_BGRA32:
523 case PIXEL_FORMAT_BGRX32:
524 return general_YUV444ToRGB_8u_P3AC4R_BGRX(pSrc, srcStep, pDst, dstStep, DstFormat, roi);
527 return general_YUV444ToRGB_8u_P3AC4R_general(pSrc, srcStep, pDst, dstStep, DstFormat,
536static void general_YUV420ToRGB_8u_P3AC4R_double_line(BYTE* WINPR_RESTRICT pEven,
537 BYTE* WINPR_RESTRICT pOdd, UINT32 DstFormat,
538 const BYTE* WINPR_RESTRICT pYeven,
539 const BYTE* WINPR_RESTRICT pYodd,
540 const BYTE* WINPR_RESTRICT pU,
541 const BYTE* WINPR_RESTRICT pV, UINT32 width,
542 fkt_writePixel writePixel, UINT32 formatSize)
546 for (; x < width / 2; x++)
548 const BYTE U = pU[x];
549 const BYTE V = pV[x];
550 const BYTE eY0 = pYeven[2ULL * x + 0];
551 const BYTE eY1 = pYeven[2ULL * x + 1];
552 writeYUVPixel(&pEven[2ULL * x * formatSize], DstFormat, eY0, U, V, writePixel);
553 writeYUVPixel(&pEven[(2ULL * x + 1) * formatSize], DstFormat, eY1, U, V, writePixel);
555 const BYTE oY0 = pYodd[2ULL * x + 0];
556 const BYTE oY1 = pYodd[2ULL * x + 1];
557 writeYUVPixel(&pOdd[2ULL * x * formatSize], DstFormat, oY0, U, V, writePixel);
558 writeYUVPixel(&pOdd[(2ULL * x + 1) * formatSize], DstFormat, oY1, U, V, writePixel);
561 for (; x < (width + 1) / 2; x++)
563 const BYTE U = pU[x];
564 const BYTE V = pV[x];
565 const BYTE eY0 = pYeven[2ULL * x + 0];
566 writeYUVPixel(&pEven[2ULL * x * formatSize], DstFormat, eY0, U, V, writePixel);
568 const BYTE oY0 = pYodd[2ULL * x + 0];
569 writeYUVPixel(&pOdd[2ULL * x * formatSize], DstFormat, oY0, U, V, writePixel);
573static void general_YUV420ToRGB_8u_P3AC4R_single_line(BYTE* WINPR_RESTRICT pEven, UINT32 DstFormat,
574 const BYTE* WINPR_RESTRICT pYeven,
575 const BYTE* WINPR_RESTRICT pU,
576 const BYTE* WINPR_RESTRICT pV, UINT32 width,
577 fkt_writePixel writePixel, UINT32 formatSize)
581 for (; x < width / 2; x++)
583 const BYTE U = pU[x];
584 const BYTE V = pV[x];
585 const BYTE eY0 = pYeven[2ULL * x + 0];
586 const BYTE eY1 = pYeven[2ULL * x + 1];
587 writeYUVPixel(&pEven[2ULL * x * formatSize], DstFormat, eY0, U, V, writePixel);
588 writeYUVPixel(&pEven[(2ULL * x + 1) * formatSize], DstFormat, eY1, U, V, writePixel);
591 for (; x < (width + 1) / 2; x++)
593 const BYTE U = pU[x];
594 const BYTE V = pV[x];
595 const BYTE eY0 = pYeven[2ULL * x + 0];
596 writeYUVPixel(&pEven[2ULL * x * formatSize], DstFormat, eY0, U, V, writePixel);
600static pstatus_t general_YUV420ToRGB_8u_P3AC4R(
const BYTE* WINPR_RESTRICT pSrc[3],
601 const UINT32 srcStep[3], BYTE* WINPR_RESTRICT pDst,
602 UINT32 dstStep, UINT32 DstFormat,
606 const DWORD formatSize = FreeRDPGetBytesPerPixel(DstFormat);
607 fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, FALSE);
608 const UINT32 nWidth = roi->width;
609 const UINT32 nHeight = roi->height;
612 for (; y < nHeight / 2; y++)
614 const BYTE* pYe = &pSrc[0][(2ULL * y + 0) * srcStep[0]];
615 const BYTE* pYo = &pSrc[0][(2ULL * y + 1) * srcStep[0]];
616 const BYTE* pU = &pSrc[1][1ULL * srcStep[1] * y];
617 const BYTE* pV = &pSrc[2][1ULL * srcStep[2] * y];
618 BYTE* pRGBeven = &pDst[2ULL * y * dstStep];
619 BYTE* pRGBodd = &pDst[(2ULL * y + 1) * dstStep];
620 general_YUV420ToRGB_8u_P3AC4R_double_line(pRGBeven, pRGBodd, DstFormat, pYe, pYo, pU, pV,
621 nWidth, writePixel, formatSize);
625 for (; y < (nHeight + 1) / 2; y++)
627 const BYTE* pY = &pSrc[0][2ULL * srcStep[0] * y];
628 const BYTE* pU = &pSrc[1][1ULL * srcStep[1] * y];
629 const BYTE* pV = &pSrc[2][1ULL * srcStep[2] * y];
630 BYTE* pEven = &pDst[2ULL * y * dstStep];
632 general_YUV420ToRGB_8u_P3AC4R_single_line(pEven, DstFormat, pY, pU, pV, nWidth, writePixel,
636 return PRIMITIVES_SUCCESS;
639static inline void BGRX_fillYUV(
size_t offset,
const BYTE* WINPR_RESTRICT pRGB[2],
640 BYTE* WINPR_RESTRICT pY[2], BYTE* WINPR_RESTRICT pU[2],
641 BYTE* WINPR_RESTRICT pV[2])
648 const UINT32 SrcFormat = PIXEL_FORMAT_BGRX32;
649 const UINT32 bpp = 4;
651 for (
size_t i = 0; i < 2; i++)
653 for (
size_t j = 0; j < 2; j++)
658 const UINT32 color = FreeRDPReadColor(&pRGB[i][(offset + j) * bpp], SrcFormat);
659 FreeRDPSplitColor(color, SrcFormat, &R, &G, &B,
nullptr,
nullptr);
660 pY[i][offset + j] = RGB2Y(R, G, B);
661 pU[i][offset + j] = RGB2U(R, G, B);
662 pV[i][offset + j] = RGB2V(R, G, B);
667 const INT32 avgU = (pU[0][offset] + pU[0][offset + 1] + pU[1][offset] + pU[1][offset + 1]) / 4;
668 pU[0][offset] = CONDITIONAL_CLIP(avgU, pU[0][offset]);
669 const INT32 avgV = (pV[0][offset] + pV[0][offset + 1] + pV[1][offset] + pV[1][offset + 1]) / 4;
670 pV[0][offset] = CONDITIONAL_CLIP(avgV, pV[0][offset]);
673static inline void BGRX_fillYUV_single(
size_t offset,
const BYTE* WINPR_RESTRICT pRGB,
674 BYTE* WINPR_RESTRICT pY, BYTE* WINPR_RESTRICT pU,
675 BYTE* WINPR_RESTRICT pV)
682 const UINT32 SrcFormat = PIXEL_FORMAT_BGRX32;
683 const UINT32 bpp = 4;
685 for (
size_t j = 0; j < 2; j++)
690 const UINT32 color = FreeRDPReadColor(&pRGB[(offset + j) * bpp], SrcFormat);
691 FreeRDPSplitColor(color, SrcFormat, &R, &G, &B,
nullptr,
nullptr);
692 pY[offset + j] = RGB2Y(R, G, B);
693 pU[offset + j] = RGB2U(R, G, B);
694 pV[offset + j] = RGB2V(R, G, B);
698static inline void general_BGRXToYUV444_DOUBLE_ROW(
const BYTE* WINPR_RESTRICT pRGB[2],
699 BYTE* WINPR_RESTRICT pY[2],
700 BYTE* WINPR_RESTRICT pU[2],
701 BYTE* WINPR_RESTRICT pV[2], UINT32 nWidth)
703 for (
size_t x = 0; x < nWidth; x += 2)
705 BGRX_fillYUV(x, pRGB, pY, pU, pV);
709static inline void general_BGRXToYUV444_SINGLE_ROW(
const BYTE* WINPR_RESTRICT pRGB,
710 BYTE* WINPR_RESTRICT pY, BYTE* WINPR_RESTRICT pU,
711 BYTE* WINPR_RESTRICT pV, UINT32 nWidth)
713 for (
size_t x = 0; x < nWidth; x += 2)
715 BGRX_fillYUV_single(x, pRGB, pY, pU, pV);
719static inline pstatus_t general_RGBToYUV444_8u_P3AC4R_BGRX(
const BYTE* WINPR_RESTRICT pSrc,
720 const UINT32 srcStep,
721 BYTE* WINPR_RESTRICT pDst[3],
722 const UINT32 dstStep[3],
725 const UINT32 nWidth = roi->width;
726 const UINT32 nHeight = roi->height;
729 for (; y < nHeight - nHeight % 2; y += 2)
731 const BYTE* pRGB[] = { pSrc + y * srcStep, pSrc + (y + 1) * srcStep };
732 BYTE* pY[] = { pDst[0] + y * dstStep[0], pDst[0] + (y + 1) * dstStep[0] };
733 BYTE* pU[] = { pDst[1] + y * dstStep[1], pDst[1] + (y + 1) * dstStep[1] };
734 BYTE* pV[] = { pDst[2] + y * dstStep[2], pDst[2] + (y + 1) * dstStep[2] };
736 general_BGRXToYUV444_DOUBLE_ROW(pRGB, pY, pU, pV, nWidth);
739 for (; y < nHeight; y++)
741 const BYTE* pRGB = pSrc + y * srcStep;
742 BYTE* pY = pDst[0] + y * dstStep[0];
743 BYTE* pU = pDst[1] + y * dstStep[1];
744 BYTE* pV = pDst[2] + y * dstStep[2];
746 general_BGRXToYUV444_SINGLE_ROW(pRGB, pY, pU, pV, nWidth);
749 return PRIMITIVES_SUCCESS;
752static inline void fillYUV(
size_t offset,
const BYTE* WINPR_RESTRICT pRGB[2], UINT32 SrcFormat,
753 BYTE* WINPR_RESTRICT pY[2], BYTE* WINPR_RESTRICT pU[2],
754 BYTE* WINPR_RESTRICT pV[2])
760 const UINT32 bpp = FreeRDPGetBytesPerPixel(SrcFormat);
764 for (
size_t i = 0; i < 2; i++)
766 for (
size_t j = 0; j < 2; j++)
771 const UINT32 color = FreeRDPReadColor(&pRGB[i][(offset + j) * bpp], SrcFormat);
772 FreeRDPSplitColor(color, SrcFormat, &R, &G, &B,
nullptr,
nullptr);
773 const BYTE y = RGB2Y(R, G, B);
774 const BYTE u = RGB2U(R, G, B);
775 const BYTE v = RGB2V(R, G, B);
778 pY[i][offset + j] = y;
779 pU[i][offset + j] = u;
780 pV[i][offset + j] = v;
786 pU[0][offset] = CLIP(avgU);
789 pV[0][offset] = CLIP(avgV);
792static inline void fillYUV_single(
size_t offset,
const BYTE* WINPR_RESTRICT pRGB, UINT32 SrcFormat,
793 BYTE* WINPR_RESTRICT pY, BYTE* WINPR_RESTRICT pU,
794 BYTE* WINPR_RESTRICT pV)
800 const UINT32 bpp = FreeRDPGetBytesPerPixel(SrcFormat);
802 for (
size_t j = 0; j < 2; j++)
807 const UINT32 color = FreeRDPReadColor(&pRGB[(offset + j) * bpp], SrcFormat);
808 FreeRDPSplitColor(color, SrcFormat, &R, &G, &B,
nullptr,
nullptr);
809 const BYTE y = RGB2Y(R, G, B);
810 const BYTE u = RGB2U(R, G, B);
811 const BYTE v = RGB2V(R, G, B);
818static inline void general_RGBToYUV444_DOUBLE_ROW(
const BYTE* WINPR_RESTRICT pRGB[2],
819 UINT32 SrcFormat, BYTE* WINPR_RESTRICT pY[2],
820 BYTE* WINPR_RESTRICT pU[2],
821 BYTE* WINPR_RESTRICT pV[2], UINT32 nWidth)
823 for (
size_t x = 0; x < nWidth; x += 2)
825 fillYUV(x, pRGB, SrcFormat, pY, pU, pV);
829static inline void general_RGBToYUV444_SINGLE_ROW(
const BYTE* WINPR_RESTRICT pRGB, UINT32 SrcFormat,
830 BYTE* WINPR_RESTRICT pY, BYTE* WINPR_RESTRICT pU,
831 BYTE* WINPR_RESTRICT pV, UINT32 nWidth)
833 for (
size_t x = 0; x < nWidth; x += 2)
835 fillYUV_single(x, pRGB, SrcFormat, pY, pU, pV);
839static inline pstatus_t general_RGBToYUV444_8u_P3AC4R_RGB(
const BYTE* WINPR_RESTRICT pSrc,
840 UINT32 SrcFormat,
const UINT32 srcStep,
841 BYTE* WINPR_RESTRICT pDst[3],
842 const UINT32 dstStep[3],
845 const UINT32 nWidth = roi->width;
846 const UINT32 nHeight = roi->height;
849 for (; y < nHeight - nHeight % 2; y += 2)
851 const BYTE* pRGB[] = { pSrc + y * srcStep, pSrc + (y + 1) * srcStep };
852 BYTE* pY[] = { &pDst[0][y * dstStep[0]], &pDst[0][(y + 1) * dstStep[0]] };
853 BYTE* pU[] = { &pDst[1][y * dstStep[1]], &pDst[1][(y + 1) * dstStep[1]] };
854 BYTE* pV[] = { &pDst[2][y * dstStep[2]], &pDst[2][(y + 1) * dstStep[2]] };
856 general_RGBToYUV444_DOUBLE_ROW(pRGB, SrcFormat, pY, pU, pV, nWidth);
858 for (; y < nHeight; y++)
860 const BYTE* pRGB = pSrc + y * srcStep;
861 BYTE* pY = &pDst[0][y * dstStep[0]];
862 BYTE* pU = &pDst[1][y * dstStep[1]];
863 BYTE* pV = &pDst[2][y * dstStep[2]];
865 general_RGBToYUV444_SINGLE_ROW(pRGB, SrcFormat, pY, pU, pV, nWidth);
868 return PRIMITIVES_SUCCESS;
871static pstatus_t general_RGBToYUV444_8u_P3AC4R(
const BYTE* WINPR_RESTRICT pSrc, UINT32 SrcFormat,
872 const UINT32 srcStep, BYTE* WINPR_RESTRICT pDst[3],
873 const UINT32 dstStep[3],
878 case PIXEL_FORMAT_BGRA32:
879 case PIXEL_FORMAT_BGRX32:
880 return general_RGBToYUV444_8u_P3AC4R_BGRX(pSrc, srcStep, pDst, dstStep, roi);
882 return general_RGBToYUV444_8u_P3AC4R_RGB(pSrc, SrcFormat, srcStep, pDst, dstStep, roi);
886static inline void fillI444_single(
size_t offset,
const BYTE* WINPR_RESTRICT pRGB, UINT32 SrcFormat,
887 BYTE* WINPR_RESTRICT pY, BYTE* WINPR_RESTRICT pU,
888 BYTE* WINPR_RESTRICT pV)
895 const UINT32 bpp = FreeRDPGetBytesPerPixel(SrcFormat);
900 const UINT32 color = FreeRDPReadColor(&pRGB[offset * bpp], SrcFormat);
901 FreeRDPSplitColor(color, SrcFormat, &R, &G, &B,
nullptr,
nullptr);
902 const BYTE y = RGB2Y(R, G, B);
903 const BYTE u = RGB2U(R, G, B);
904 const BYTE v = RGB2V(R, G, B);
910static inline void general_RGBToI444_SINGLE_ROW(
const BYTE* WINPR_RESTRICT pRGB, UINT32 SrcFormat,
911 BYTE* WINPR_RESTRICT pY, BYTE* WINPR_RESTRICT pU,
912 BYTE* WINPR_RESTRICT pV, UINT32 nWidth)
914 for (
size_t x = 0; x < nWidth; x++)
916 fillI444_single(x, pRGB, SrcFormat, pY, pU, pV);
920static inline pstatus_t general_RGBToI444_8u_RGB(
const BYTE* WINPR_RESTRICT pSrc, UINT32 SrcFormat,
921 const UINT32 srcStep, BYTE* WINPR_RESTRICT pDst[3],
922 const UINT32 dstStep[3],
925 const UINT32 nWidth = roi->width;
926 const UINT32 nHeight = roi->height;
928 for (
size_t y = 0; y < nHeight; y++)
930 const BYTE* pRGB = pSrc + y * srcStep;
931 BYTE* pY = &pDst[0][y * dstStep[0]];
932 BYTE* pU = &pDst[1][y * dstStep[1]];
933 BYTE* pV = &pDst[2][y * dstStep[2]];
935 general_RGBToI444_SINGLE_ROW(pRGB, SrcFormat, pY, pU, pV, nWidth);
938 return PRIMITIVES_SUCCESS;
941static pstatus_t general_RGBToI444_8u(
const BYTE* WINPR_RESTRICT pSrc, UINT32 SrcFormat,
942 const UINT32 srcStep, BYTE* WINPR_RESTRICT pDst[3],
943 const UINT32 dstStep[3],
949 return general_RGBToI444_8u_RGB(pSrc, SrcFormat, srcStep, pDst, dstStep, roi);
953static inline pstatus_t general_RGBToYUV420_BGRX(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcStep,
954 BYTE* WINPR_RESTRICT pDst[3],
955 const UINT32 dstStep[3],
961 size_t x4 = srcStep + 4;
964 size_t y3 = dstStep[0];
965 size_t y4 = dstStep[0] + 1;
966 UINT32 max_x = roi->width - 1;
969 for (
size_t i = 0; y < roi->height - roi->height % 2; y += 2, i++)
971 const BYTE* src = pSrc + y * srcStep;
972 BYTE* ydst = pDst[0] + y * dstStep[0];
973 BYTE* udst = pDst[1] + i * dstStep[1];
974 BYTE* vdst = pDst[2] + i * dstStep[2];
976 for (
size_t x = 0; x < roi->width; x += 2)
985 Ba = B = *(src + x1 + 0);
986 Ga = G = *(src + x1 + 1);
987 Ra = R = *(src + x1 + 2);
988 ydst[y1] = RGB2Y(R, G, B);
993 Ba += B = *(src + x2 + 0);
994 Ga += G = *(src + x2 + 1);
995 Ra += R = *(src + x2 + 2);
996 ydst[y2] = RGB2Y(R, G, B);
1000 Ba += B = *(src + x3 + 0);
1001 Ga += G = *(src + x3 + 1);
1002 Ra += R = *(src + x3 + 2);
1003 ydst[y3] = RGB2Y(R, G, B);
1008 Ba += B = *(src + x4 + 0);
1009 Ga += G = *(src + x4 + 1);
1010 Ra += R = *(src + x4 + 2);
1011 ydst[y4] = RGB2Y(R, G, B);
1017 *udst++ = RGB2U(Ra, Ga, Ba);
1018 *vdst++ = RGB2V(Ra, Ga, Ba);
1024 for (; y < roi->height; y++)
1026 const BYTE* src = pSrc + y * srcStep;
1027 BYTE* ydst = pDst[0] + y * dstStep[0];
1028 BYTE* udst = pDst[1] + (y / 2) * dstStep[1];
1029 BYTE* vdst = pDst[2] + (y / 2) * dstStep[2];
1031 for (
size_t x = 0; x < roi->width; x += 2)
1040 Ba = B = *(src + x1 + 0);
1041 Ga = G = *(src + x1 + 1);
1042 Ra = R = *(src + x1 + 2);
1043 ydst[y1] = RGB2Y(R, G, B);
1048 Ba += B = *(src + x2 + 0);
1049 Ga += G = *(src + x2 + 1);
1050 Ra += R = *(src + x2 + 2);
1051 ydst[y2] = RGB2Y(R, G, B);
1057 *udst++ = RGB2U(Ra, Ga, Ba);
1058 *vdst++ = RGB2V(Ra, Ga, Ba);
1064 return PRIMITIVES_SUCCESS;
1067static inline pstatus_t general_RGBToYUV420_RGBX(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcStep,
1068 BYTE* WINPR_RESTRICT pDst[3],
1069 const UINT32 dstStep[3],
1074 size_t x3 = srcStep;
1075 size_t x4 = srcStep + 4;
1078 size_t y3 = dstStep[0];
1079 size_t y4 = dstStep[0] + 1;
1080 UINT32 max_x = roi->width - 1;
1083 for (
size_t i = 0; y < roi->height - roi->height % 2; y += 2, i++)
1085 const BYTE* src = pSrc + y * srcStep;
1086 BYTE* ydst = pDst[0] + y * dstStep[0];
1087 BYTE* udst = pDst[1] + i * dstStep[1];
1088 BYTE* vdst = pDst[2] + i * dstStep[2];
1090 for (UINT32 x = 0; x < roi->width; x += 2)
1092 BYTE R = *(src + x1 + 0);
1093 BYTE G = *(src + x1 + 1);
1094 BYTE B = *(src + x1 + 2);
1099 ydst[y1] = RGB2Y(R, G, B);
1104 R = *(src + x2 + 0);
1105 G = *(src + x2 + 1);
1106 B = *(src + x2 + 2);
1110 ydst[y2] = RGB2Y(R, G, B);
1114 R = *(src + x3 + 0);
1115 G = *(src + x3 + 1);
1116 B = *(src + x3 + 2);
1121 ydst[y3] = RGB2Y(R, G, B);
1126 R = *(src + x4 + 0);
1127 G = *(src + x4 + 1);
1128 B = *(src + x4 + 2);
1133 ydst[y4] = RGB2Y(R, G, B);
1139 *udst++ = RGB2U(Ra, Ga, Ba);
1140 *vdst++ = RGB2V(Ra, Ga, Ba);
1146 for (; y < roi->height; y++)
1148 const BYTE* src = pSrc + y * srcStep;
1149 BYTE* ydst = pDst[0] + y * dstStep[0];
1150 BYTE* udst = pDst[1] + (y / 2) * dstStep[1];
1151 BYTE* vdst = pDst[2] + (y / 2) * dstStep[2];
1153 for (UINT32 x = 0; x < roi->width; x += 2)
1155 BYTE R = *(src + x1 + 0);
1156 BYTE G = *(src + x1 + 1);
1157 BYTE B = *(src + x1 + 2);
1162 ydst[y1] = RGB2Y(R, G, B);
1167 R = *(src + x2 + 0);
1168 G = *(src + x2 + 1);
1169 B = *(src + x2 + 2);
1173 ydst[y2] = RGB2Y(R, G, B);
1179 *udst++ = RGB2U(Ra, Ga, Ba);
1180 *vdst++ = RGB2V(Ra, Ga, Ba);
1186 return PRIMITIVES_SUCCESS;
1189static inline pstatus_t general_RGBToYUV420_ANY(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcFormat,
1190 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst[3],
1191 const UINT32 dstStep[3],
1194 const UINT32 bpp = FreeRDPGetBytesPerPixel(srcFormat);
1197 size_t x3 = srcStep;
1198 size_t x4 = srcStep + bpp;
1201 size_t y3 = dstStep[0];
1202 size_t y4 = dstStep[0] + 1;
1203 UINT32 max_x = roi->width - 1;
1206 for (
size_t i = 0; y < roi->height - roi->height % 2; y += 2, i++)
1208 const BYTE* src = pSrc + y * srcStep;
1209 BYTE* ydst = pDst[0] + y * dstStep[0];
1210 BYTE* udst = pDst[1] + i * dstStep[1];
1211 BYTE* vdst = pDst[2] + i * dstStep[2];
1213 for (
size_t x = 0; x < roi->width; x += 2)
1223 color = FreeRDPReadColor(src + x1, srcFormat);
1224 FreeRDPSplitColor(color, srcFormat, &R, &G, &B,
nullptr,
nullptr);
1228 ydst[y1] = RGB2Y(R, G, B);
1233 color = FreeRDPReadColor(src + x2, srcFormat);
1234 FreeRDPSplitColor(color, srcFormat, &R, &G, &B,
nullptr,
nullptr);
1238 ydst[y2] = RGB2Y(R, G, B);
1242 color = FreeRDPReadColor(src + x3, srcFormat);
1243 FreeRDPSplitColor(color, srcFormat, &R, &G, &B,
nullptr,
nullptr);
1247 ydst[y3] = RGB2Y(R, G, B);
1252 color = FreeRDPReadColor(src + x4, srcFormat);
1253 FreeRDPSplitColor(color, srcFormat, &R, &G, &B,
nullptr,
nullptr);
1257 ydst[y4] = RGB2Y(R, G, B);
1263 *udst++ = RGB2U(Ra, Ga, Ba);
1264 *vdst++ = RGB2V(Ra, Ga, Ba);
1270 for (; y < roi->height; y++)
1272 const BYTE* src = pSrc + y * srcStep;
1273 BYTE* ydst = pDst[0] + y * dstStep[0];
1274 BYTE* udst = pDst[1] + (y / 2) * dstStep[1];
1275 BYTE* vdst = pDst[2] + (y / 2) * dstStep[2];
1277 for (
size_t x = 0; x < roi->width; x += 2)
1283 UINT32 color = FreeRDPReadColor(src + x1, srcFormat);
1284 FreeRDPSplitColor(color, srcFormat, &R, &G, &B,
nullptr,
nullptr);
1288 ydst[y1] = RGB2Y(R, G, B);
1293 color = FreeRDPReadColor(src + x2, srcFormat);
1294 FreeRDPSplitColor(color, srcFormat, &R, &G, &B,
nullptr,
nullptr);
1298 ydst[y2] = RGB2Y(R, G, B);
1304 *udst++ = RGB2U(Ra, Ga, Ba);
1305 *vdst++ = RGB2V(Ra, Ga, Ba);
1311 return PRIMITIVES_SUCCESS;
1314static pstatus_t general_RGBToYUV420_8u_P3AC4R(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcFormat,
1315 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst[3],
1316 const UINT32 dstStep[3],
1321 case PIXEL_FORMAT_BGRA32:
1322 case PIXEL_FORMAT_BGRX32:
1323 return general_RGBToYUV420_BGRX(pSrc, srcStep, pDst, dstStep, roi);
1325 case PIXEL_FORMAT_RGBA32:
1326 case PIXEL_FORMAT_RGBX32:
1327 return general_RGBToYUV420_RGBX(pSrc, srcStep, pDst, dstStep, roi);
1330 return general_RGBToYUV420_ANY(pSrc, srcFormat, srcStep, pDst, dstStep, roi);
1334static inline void int_general_RGBToAVC444YUV_BGRX_DOUBLE_ROW(
1335 size_t offset,
const BYTE* WINPR_RESTRICT pSrcEven,
const BYTE* WINPR_RESTRICT pSrcOdd,
1336 BYTE* WINPR_RESTRICT b1Even, BYTE* WINPR_RESTRICT b1Odd, BYTE* WINPR_RESTRICT b2,
1337 BYTE* WINPR_RESTRICT b3, BYTE* WINPR_RESTRICT b4, BYTE* WINPR_RESTRICT b5,
1338 BYTE* WINPR_RESTRICT b6, BYTE* WINPR_RESTRICT b7, UINT32 width)
1340 for (
size_t x = offset; x < width; x += 2)
1342 const BYTE* srcEven = &pSrcEven[4ULL * x];
1343 const BYTE* srcOdd = &pSrcOdd[4ULL * x];
1344 const BOOL lastX = (x + 1) >= width;
1359 const BYTE b = *srcEven++;
1360 const BYTE g = *srcEven++;
1361 const BYTE r = *srcEven++;
1363 Y1e = Y2e = Y1o = Y2o = RGB2Y(r, g, b);
1364 U1e = U2e = U1o = U2o = RGB2U(r, g, b);
1365 V1e = V2e = V1o = V2o = RGB2V(r, g, b);
1370 const BYTE b = *srcEven++;
1371 const BYTE g = *srcEven++;
1372 const BYTE r = *srcEven++;
1374 Y2e = RGB2Y(r, g, b);
1375 U2e = RGB2U(r, g, b);
1376 V2e = RGB2V(r, g, b);
1381 const BYTE b = *srcOdd++;
1382 const BYTE g = *srcOdd++;
1383 const BYTE r = *srcOdd++;
1385 Y1o = Y2o = RGB2Y(r, g, b);
1386 U1o = U2o = RGB2U(r, g, b);
1387 V1o = V2o = RGB2V(r, g, b);
1390 if (b1Odd && !lastX)
1392 const BYTE b = *srcOdd++;
1393 const BYTE g = *srcOdd++;
1394 const BYTE r = *srcOdd++;
1396 Y2o = RGB2Y(r, g, b);
1397 U2o = RGB2U(r, g, b);
1398 V2o = RGB2V(r, g, b);
1414 const BYTE Uavg = WINPR_ASSERTING_INT_CAST(BYTE, ((UINT16)U1e + U2e + U1o + U2o) / 4);
1415 const BYTE Vavg = WINPR_ASSERTING_INT_CAST(BYTE, ((UINT16)V1e + V2e + V1o + V2o) / 4);
1442void general_RGBToAVC444YUV_BGRX_DOUBLE_ROW(
size_t offset,
const BYTE* WINPR_RESTRICT pSrcEven,
1443 const BYTE* WINPR_RESTRICT pSrcOdd,
1444 BYTE* WINPR_RESTRICT b1Even, BYTE* WINPR_RESTRICT b1Odd,
1445 BYTE* WINPR_RESTRICT b2, BYTE* WINPR_RESTRICT b3,
1446 BYTE* WINPR_RESTRICT b4, BYTE* WINPR_RESTRICT b5,
1447 BYTE* WINPR_RESTRICT b6, BYTE* WINPR_RESTRICT b7,
1450 int_general_RGBToAVC444YUV_BGRX_DOUBLE_ROW(offset, pSrcEven, pSrcOdd, b1Even, b1Odd, b2, b3, b4,
1454static inline pstatus_t general_RGBToAVC444YUV_BGRX(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcStep,
1455 BYTE* WINPR_RESTRICT pDst1[3],
1456 const UINT32 dst1Step[3],
1457 BYTE* WINPR_RESTRICT pDst2[3],
1458 const UINT32 dst2Step[3],
1466 for (; y < roi->height - roi->height % 2; y += 2)
1468 const BYTE* srcEven = pSrc + 1ULL * y * srcStep;
1469 const BYTE* srcOdd = pSrc + 1ULL * (y + 1) * srcStep;
1470 const size_t i = y >> 1;
1471 const size_t n = (i & (uint32_t)~7) + i;
1472 BYTE* b1Even = pDst1[0] + 1ULL * y * dst1Step[0];
1473 BYTE* b1Odd = (b1Even + dst1Step[0]);
1474 BYTE* b2 = pDst1[1] + 1ULL * (y / 2) * dst1Step[1];
1475 BYTE* b3 = pDst1[2] + 1ULL * (y / 2) * dst1Step[2];
1476 BYTE* b4 = pDst2[0] + 1ULL * dst2Step[0] * n;
1477 BYTE* b5 = b4 + 8ULL * dst2Step[0];
1478 BYTE* b6 = pDst2[1] + 1ULL * (y / 2) * dst2Step[1];
1479 BYTE* b7 = pDst2[2] + 1ULL * (y / 2) * dst2Step[2];
1480 int_general_RGBToAVC444YUV_BGRX_DOUBLE_ROW(0, srcEven, srcOdd, b1Even, b1Odd, b2, b3, b4,
1481 b5, b6, b7, roi->width);
1483 for (; y < roi->height; y++)
1485 const BYTE* srcEven = pSrc + 1ULL * y * srcStep;
1486 BYTE* b1Even = pDst1[0] + 1ULL * y * dst1Step[0];
1487 BYTE* b2 = pDst1[1] + 1ULL * (y / 2) * dst1Step[1];
1488 BYTE* b3 = pDst1[2] + 1ULL * (y / 2) * dst1Step[2];
1489 BYTE* b6 = pDst2[1] + 1ULL * (y / 2) * dst2Step[1];
1490 BYTE* b7 = pDst2[2] + 1ULL * (y / 2) * dst2Step[2];
1491 int_general_RGBToAVC444YUV_BGRX_DOUBLE_ROW(0, srcEven,
nullptr, b1Even,
nullptr, b2, b3,
1492 nullptr,
nullptr, b6, b7, roi->width);
1495 return PRIMITIVES_SUCCESS;
1498static inline void general_RGBToAVC444YUV_RGBX_DOUBLE_ROW(
1499 const BYTE* WINPR_RESTRICT srcEven,
const BYTE* WINPR_RESTRICT srcOdd,
1500 BYTE* WINPR_RESTRICT b1Even, BYTE* WINPR_RESTRICT b1Odd, BYTE* WINPR_RESTRICT b2,
1501 BYTE* WINPR_RESTRICT b3, BYTE* WINPR_RESTRICT b4, BYTE* WINPR_RESTRICT b5,
1502 BYTE* WINPR_RESTRICT b6, BYTE* WINPR_RESTRICT b7, UINT32 width)
1504 for (UINT32 x = 0; x < width; x += 2)
1506 const BOOL lastX = (x + 1) >= width;
1521 const BYTE r = *srcEven++;
1522 const BYTE g = *srcEven++;
1523 const BYTE b = *srcEven++;
1525 Y1e = Y2e = Y1o = Y2o = RGB2Y(r, g, b);
1526 U1e = U2e = U1o = U2o = RGB2U(r, g, b);
1527 V1e = V2e = V1o = V2o = RGB2V(r, g, b);
1532 const BYTE r = *srcEven++;
1533 const BYTE g = *srcEven++;
1534 const BYTE b = *srcEven++;
1536 Y2e = RGB2Y(r, g, b);
1537 U2e = RGB2U(r, g, b);
1538 V2e = RGB2V(r, g, b);
1543 const BYTE r = *srcOdd++;
1544 const BYTE g = *srcOdd++;
1545 const BYTE b = *srcOdd++;
1547 Y1o = Y2o = RGB2Y(r, g, b);
1548 U1o = U2o = RGB2U(r, g, b);
1549 V1o = V2o = RGB2V(r, g, b);
1552 if (b1Odd && !lastX)
1554 const BYTE r = *srcOdd++;
1555 const BYTE g = *srcOdd++;
1556 const BYTE b = *srcOdd++;
1558 Y2o = RGB2Y(r, g, b);
1559 U2o = RGB2U(r, g, b);
1560 V2o = RGB2V(r, g, b);
1576 const BYTE Uavg = WINPR_ASSERTING_INT_CAST(BYTE, ((UINT16)U1e + U2e + U1o + U2o) / 4);
1577 const BYTE Vavg = WINPR_ASSERTING_INT_CAST(BYTE, ((UINT16)V1e + V2e + V1o + V2o) / 4);
1604static inline pstatus_t general_RGBToAVC444YUV_RGBX(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcStep,
1605 BYTE* WINPR_RESTRICT pDst1[3],
1606 const UINT32 dst1Step[3],
1607 BYTE* WINPR_RESTRICT pDst2[3],
1608 const UINT32 dst2Step[3],
1617 for (; y < roi->height - roi->height % 2; y += 2)
1619 const BOOL last = (y >= (roi->height - 1));
1620 const BYTE* srcEven = pSrc + 1ULL * y * srcStep;
1621 const BYTE* srcOdd = pSrc + 1ULL * (y + 1) * srcStep;
1622 const size_t i = y >> 1;
1623 const size_t n = (i & (size_t)~7) + i;
1624 BYTE* b1Even = pDst1[0] + 1ULL * y * dst1Step[0];
1625 BYTE* b1Odd = !last ? (b1Even + dst1Step[0]) : nullptr;
1626 BYTE* b2 = pDst1[1] + 1ULL * (y / 2) * dst1Step[1];
1627 BYTE* b3 = pDst1[2] + 1ULL * (y / 2) * dst1Step[2];
1628 BYTE* b4 = pDst2[0] + 1ULL * dst2Step[0] * n;
1629 BYTE* b5 = b4 + 8ULL * dst2Step[0];
1630 BYTE* b6 = pDst2[1] + 1ULL * (y / 2) * dst2Step[1];
1631 BYTE* b7 = pDst2[2] + 1ULL * (y / 2) * dst2Step[2];
1632 general_RGBToAVC444YUV_RGBX_DOUBLE_ROW(srcEven, srcOdd, b1Even, b1Odd, b2, b3, b4, b5, b6,
1635 for (; y < roi->height; y++)
1637 const BYTE* srcEven = pSrc + 1ULL * y * srcStep;
1638 BYTE* b1Even = pDst1[0] + 1ULL * y * dst1Step[0];
1639 BYTE* b2 = pDst1[1] + 1ULL * (y / 2) * dst1Step[1];
1640 BYTE* b3 = pDst1[2] + 1ULL * (y / 2) * dst1Step[2];
1641 BYTE* b6 = pDst2[1] + 1ULL * (y / 2) * dst2Step[1];
1642 BYTE* b7 = pDst2[2] + 1ULL * (y / 2) * dst2Step[2];
1643 general_RGBToAVC444YUV_RGBX_DOUBLE_ROW(srcEven,
nullptr, b1Even,
nullptr, b2, b3,
nullptr,
1644 nullptr, b6, b7, roi->width);
1646 return PRIMITIVES_SUCCESS;
1649static inline void general_RGBToAVC444YUV_ANY_DOUBLE_ROW(
1650 const BYTE* WINPR_RESTRICT srcEven,
const BYTE* WINPR_RESTRICT srcOdd, UINT32 srcFormat,
1651 BYTE* WINPR_RESTRICT b1Even, BYTE* WINPR_RESTRICT b1Odd, BYTE* WINPR_RESTRICT b2,
1652 BYTE* WINPR_RESTRICT b3, BYTE* WINPR_RESTRICT b4, BYTE* WINPR_RESTRICT b5,
1653 BYTE* WINPR_RESTRICT b6, BYTE* WINPR_RESTRICT b7, UINT32 width)
1655 const UINT32 bpp = FreeRDPGetBytesPerPixel(srcFormat);
1656 for (UINT32 x = 0; x < width; x += 2)
1658 const BOOL lastX = (x + 1) >= width;
1676 const UINT32 color = FreeRDPReadColor(srcEven, srcFormat);
1678 FreeRDPSplitColor(color, srcFormat, &r, &g, &b,
nullptr,
nullptr);
1679 Y1e = Y2e = Y1o = Y2o = RGB2Y(r, g, b);
1680 U1e = U2e = U1o = U2o = RGB2U(r, g, b);
1681 V1e = V2e = V1o = V2o = RGB2V(r, g, b);
1689 const UINT32 color = FreeRDPReadColor(srcEven, srcFormat);
1691 FreeRDPSplitColor(color, srcFormat, &r, &g, &b,
nullptr,
nullptr);
1692 Y2e = RGB2Y(r, g, b);
1693 U2e = RGB2U(r, g, b);
1694 V2e = RGB2V(r, g, b);
1702 const UINT32 color = FreeRDPReadColor(srcOdd, srcFormat);
1704 FreeRDPSplitColor(color, srcFormat, &r, &g, &b,
nullptr,
nullptr);
1705 Y1o = Y2o = RGB2Y(r, g, b);
1706 U1o = U2o = RGB2U(r, g, b);
1707 V1o = V2o = RGB2V(r, g, b);
1710 if (b1Odd && !lastX)
1715 const UINT32 color = FreeRDPReadColor(srcOdd, srcFormat);
1717 FreeRDPSplitColor(color, srcFormat, &r, &g, &b,
nullptr,
nullptr);
1718 Y2o = RGB2Y(r, g, b);
1719 U2o = RGB2U(r, g, b);
1720 V2o = RGB2V(r, g, b);
1736 const BYTE Uavg = WINPR_ASSERTING_INT_CAST(
1737 BYTE, ((UINT16)U1e + (UINT16)U2e + (UINT16)U1o + (UINT16)U2o) / 4);
1738 const BYTE Vavg = WINPR_ASSERTING_INT_CAST(
1739 BYTE, ((UINT16)V1e + (UINT16)V2e + (UINT16)V1o + (UINT16)V2o) / 4);
1766static inline pstatus_t
1767general_RGBToAVC444YUV_ANY(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcFormat, UINT32 srcStep,
1768 BYTE* WINPR_RESTRICT pDst1[3],
const UINT32 dst1Step[3],
1769 BYTE* WINPR_RESTRICT pDst2[3],
const UINT32 dst2Step[3],
1829 const BYTE* pMaxSrc = pSrc + 1ULL * (roi->height - 1) * srcStep;
1831 for (
size_t y = 0; y < roi->height; y += 2)
1833 WINPR_ASSERT(y < UINT32_MAX);
1835 const BOOL last = (y >= (roi->height - 1));
1836 const BYTE* srcEven = y < roi->height ? pSrc + y * srcStep : pMaxSrc;
1837 const BYTE* srcOdd = !last ? pSrc + (y + 1) * srcStep : pMaxSrc;
1838 const UINT32 i = (UINT32)y >> 1;
1839 const UINT32 n = (i & (uint32_t)~7) + i;
1840 BYTE* b1Even = pDst1[0] + y * dst1Step[0];
1841 BYTE* b1Odd = !last ? (b1Even + dst1Step[0]) : nullptr;
1842 BYTE* b2 = pDst1[1] + (y / 2) * dst1Step[1];
1843 BYTE* b3 = pDst1[2] + (y / 2) * dst1Step[2];
1844 BYTE* b4 = pDst2[0] + 1ULL * dst2Step[0] * n;
1845 BYTE* b5 = b4 + 8ULL * dst2Step[0];
1846 BYTE* b6 = pDst2[1] + (y / 2) * dst2Step[1];
1847 BYTE* b7 = pDst2[2] + (y / 2) * dst2Step[2];
1848 general_RGBToAVC444YUV_ANY_DOUBLE_ROW(srcEven, srcOdd, srcFormat, b1Even, b1Odd, b2, b3, b4,
1849 b5, b6, b7, roi->width);
1852 return PRIMITIVES_SUCCESS;
1855static inline pstatus_t general_RGBToAVC444YUV(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcFormat,
1856 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst1[3],
1857 const UINT32 dst1Step[3],
1858 BYTE* WINPR_RESTRICT pDst2[3],
1859 const UINT32 dst2Step[3],
1862 if (!pSrc || !pDst1 || !dst1Step || !pDst2 || !dst2Step)
1865 if (!pDst1[0] || !pDst1[1] || !pDst1[2])
1868 if (!dst1Step[0] || !dst1Step[1] || !dst1Step[2])
1871 if (!pDst2[0] || !pDst2[1] || !pDst2[2])
1874 if (!dst2Step[0] || !dst2Step[1] || !dst2Step[2])
1880 case PIXEL_FORMAT_BGRA32:
1881 case PIXEL_FORMAT_BGRX32:
1882 return general_RGBToAVC444YUV_BGRX(pSrc, srcStep, pDst1, dst1Step, pDst2, dst2Step,
1885 case PIXEL_FORMAT_RGBA32:
1886 case PIXEL_FORMAT_RGBX32:
1887 return general_RGBToAVC444YUV_RGBX(pSrc, srcStep, pDst1, dst1Step, pDst2, dst2Step,
1891 return general_RGBToAVC444YUV_ANY(pSrc, srcFormat, srcStep, pDst1, dst1Step, pDst2,
1895 return !PRIMITIVES_SUCCESS;
1898static inline void general_RGBToAVC444YUVv2_ANY_DOUBLE_ROW(
1899 const BYTE* WINPR_RESTRICT srcEven,
const BYTE* WINPR_RESTRICT srcOdd, UINT32 srcFormat,
1900 BYTE* WINPR_RESTRICT yLumaDstEven, BYTE* WINPR_RESTRICT yLumaDstOdd,
1901 BYTE* WINPR_RESTRICT uLumaDst, BYTE* WINPR_RESTRICT vLumaDst,
1902 BYTE* WINPR_RESTRICT yEvenChromaDst1, BYTE* WINPR_RESTRICT yEvenChromaDst2,
1903 BYTE* WINPR_RESTRICT yOddChromaDst1, BYTE* WINPR_RESTRICT yOddChromaDst2,
1904 BYTE* WINPR_RESTRICT uChromaDst1, BYTE* WINPR_RESTRICT uChromaDst2,
1905 BYTE* WINPR_RESTRICT vChromaDst1, BYTE* WINPR_RESTRICT vChromaDst2, UINT32 width)
1907 const UINT32 bpp = FreeRDPGetBytesPerPixel(srcFormat);
1909 for (UINT32 x = 0; x < width; x += 2)
1927 const UINT32 color = FreeRDPReadColor(srcEven, srcFormat);
1929 FreeRDPSplitColor(color, srcFormat, &r, &g, &b,
nullptr,
nullptr);
1930 Ya = RGB2Y(r, g, b);
1931 Ua = RGB2U(r, g, b);
1932 Va = RGB2V(r, g, b);
1940 const UINT32 color = FreeRDPReadColor(srcEven, srcFormat);
1942 FreeRDPSplitColor(color, srcFormat, &r, &g, &b,
nullptr,
nullptr);
1943 Yb = RGB2Y(r, g, b);
1944 Ub = RGB2U(r, g, b);
1945 Vb = RGB2V(r, g, b);
1959 const UINT32 color = FreeRDPReadColor(srcOdd, srcFormat);
1961 FreeRDPSplitColor(color, srcFormat, &r, &g, &b,
nullptr,
nullptr);
1962 Yc = RGB2Y(r, g, b);
1963 Uc = RGB2U(r, g, b);
1964 Vc = RGB2V(r, g, b);
1973 if (srcOdd && (x < width - 1))
1978 const UINT32 color = FreeRDPReadColor(srcOdd, srcFormat);
1980 FreeRDPSplitColor(color, srcFormat, &r, &g, &b,
nullptr,
nullptr);
1981 Yd = RGB2Y(r, g, b);
1982 Ud = RGB2U(r, g, b);
1983 Vd = RGB2V(r, g, b);
1993 *yLumaDstEven++ = Ya;
1996 *yLumaDstEven++ = Yb;
1999 *yLumaDstOdd++ = Yc;
2001 if (srcOdd && (x < width - 1))
2002 *yLumaDstOdd++ = Yd;
2005 *uLumaDst++ = (Ua + Ub + Uc + Ud) / 4;
2006 *vLumaDst++ = (Va + Vb + Vc + Vd) / 4;
2011 *yEvenChromaDst1++ = Ub;
2012 *yEvenChromaDst2++ = Vb;
2020 *yOddChromaDst1++ = Ud;
2021 *yOddChromaDst2++ = Vd;
2027 *uChromaDst1++ = Uc;
2028 *uChromaDst2++ = Vc;
2033 *vChromaDst1++ = Uc;
2034 *vChromaDst2++ = Vc;
2040static inline pstatus_t
2041general_RGBToAVC444YUVv2_ANY(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcFormat, UINT32 srcStep,
2042 BYTE* WINPR_RESTRICT pDst1[3],
const UINT32 dst1Step[3],
2043 BYTE* WINPR_RESTRICT pDst2[3],
const UINT32 dst2Step[3],
2096 if (roi->height < 1 || roi->width < 1)
2097 return !PRIMITIVES_SUCCESS;
2100 for (; y < roi->height - roi->height % 2; y += 2)
2102 const BYTE* srcEven = (pSrc + y * srcStep);
2103 const BYTE* srcOdd = (y < roi->height - 1) ? (srcEven + srcStep) :
nullptr;
2104 BYTE* dstLumaYEven = (pDst1[0] + y * dst1Step[0]);
2105 BYTE* dstLumaYOdd = (dstLumaYEven + dst1Step[0]);
2106 BYTE* dstLumaU = (pDst1[1] + (y / 2) * dst1Step[1]);
2107 BYTE* dstLumaV = (pDst1[2] + (y / 2) * dst1Step[2]);
2108 BYTE* dstEvenChromaY1 = (pDst2[0] + y * dst2Step[0]);
2109 BYTE* dstEvenChromaY2 = dstEvenChromaY1 + roi->width / 2;
2110 BYTE* dstOddChromaY1 = dstEvenChromaY1 + dst2Step[0];
2111 BYTE* dstOddChromaY2 = dstEvenChromaY2 + dst2Step[0];
2112 BYTE* dstChromaU1 = (pDst2[1] + (y / 2) * dst2Step[1]);
2113 BYTE* dstChromaV1 = (pDst2[2] + (y / 2) * dst2Step[2]);
2114 BYTE* dstChromaU2 = dstChromaU1 + roi->width / 4;
2115 BYTE* dstChromaV2 = dstChromaV1 + roi->width / 4;
2116 general_RGBToAVC444YUVv2_ANY_DOUBLE_ROW(
2117 srcEven, srcOdd, srcFormat, dstLumaYEven, dstLumaYOdd, dstLumaU, dstLumaV,
2118 dstEvenChromaY1, dstEvenChromaY2, dstOddChromaY1, dstOddChromaY2, dstChromaU1,
2119 dstChromaU2, dstChromaV1, dstChromaV2, roi->width);
2121 for (; y < roi->height; y++)
2123 const BYTE* srcEven = (pSrc + y * srcStep);
2124 BYTE* dstLumaYEven = (pDst1[0] + y * dst1Step[0]);
2125 BYTE* dstLumaU = (pDst1[1] + (y / 2) * dst1Step[1]);
2126 BYTE* dstLumaV = (pDst1[2] + (y / 2) * dst1Step[2]);
2127 BYTE* dstEvenChromaY1 = (pDst2[0] + y * dst2Step[0]);
2128 BYTE* dstEvenChromaY2 = dstEvenChromaY1 + roi->width / 2;
2129 general_RGBToAVC444YUVv2_ANY_DOUBLE_ROW(
2130 srcEven,
nullptr, srcFormat, dstLumaYEven,
nullptr, dstLumaU, dstLumaV, dstEvenChromaY1,
2131 dstEvenChromaY2,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, roi->width);
2134 return PRIMITIVES_SUCCESS;
2137static inline void int_general_RGBToAVC444YUVv2_BGRX_DOUBLE_ROW(
2138 size_t offset,
const BYTE* WINPR_RESTRICT pSrcEven,
const BYTE* WINPR_RESTRICT pSrcOdd,
2139 BYTE* WINPR_RESTRICT yLumaDstEven, BYTE* WINPR_RESTRICT yLumaDstOdd,
2140 BYTE* WINPR_RESTRICT uLumaDst, BYTE* WINPR_RESTRICT vLumaDst,
2141 BYTE* WINPR_RESTRICT yEvenChromaDst1, BYTE* WINPR_RESTRICT yEvenChromaDst2,
2142 BYTE* WINPR_RESTRICT yOddChromaDst1, BYTE* WINPR_RESTRICT yOddChromaDst2,
2143 BYTE* WINPR_RESTRICT uChromaDst1, BYTE* WINPR_RESTRICT uChromaDst2,
2144 BYTE* WINPR_RESTRICT vChromaDst1, BYTE* WINPR_RESTRICT vChromaDst2, UINT32 width)
2146 WINPR_ASSERT(pSrcEven);
2147 WINPR_ASSERT(yLumaDstEven);
2148 WINPR_ASSERT(uLumaDst);
2149 WINPR_ASSERT(vLumaDst);
2151 for (
size_t x = offset; x < width; x += 2)
2153 const BYTE* srcEven = &pSrcEven[4ULL * x];
2154 const BYTE* srcOdd = pSrcOdd ? &pSrcOdd[4ULL * x] :
nullptr;
2168 const BYTE b = *srcEven++;
2169 const BYTE g = *srcEven++;
2170 const BYTE r = *srcEven++;
2172 Ya = RGB2Y(r, g, b);
2173 Ua = RGB2U(r, g, b);
2174 Va = RGB2V(r, g, b);
2179 const BYTE b = *srcEven++;
2180 const BYTE g = *srcEven++;
2181 const BYTE r = *srcEven++;
2183 Yb = RGB2Y(r, g, b);
2184 Ub = RGB2U(r, g, b);
2185 Vb = RGB2V(r, g, b);
2196 const BYTE b = *srcOdd++;
2197 const BYTE g = *srcOdd++;
2198 const BYTE r = *srcOdd++;
2200 Yc = RGB2Y(r, g, b);
2201 Uc = RGB2U(r, g, b);
2202 Vc = RGB2V(r, g, b);
2211 if (srcOdd && (x < width - 1))
2213 const BYTE b = *srcOdd++;
2214 const BYTE g = *srcOdd++;
2215 const BYTE r = *srcOdd++;
2217 Yd = RGB2Y(r, g, b);
2218 Ud = RGB2U(r, g, b);
2219 Vd = RGB2V(r, g, b);
2229 *yLumaDstEven++ = Ya;
2232 *yLumaDstEven++ = Yb;
2234 if (srcOdd && yLumaDstOdd)
2235 *yLumaDstOdd++ = Yc;
2237 if (srcOdd && (x < width - 1) && yLumaDstOdd)
2238 *yLumaDstOdd++ = Yd;
2241 *uLumaDst++ = (Ua + Ub + Uc + Ud) / 4;
2242 *vLumaDst++ = (Va + Vb + Vc + Vd) / 4;
2247 *yEvenChromaDst1++ = Ub;
2248 *yEvenChromaDst2++ = Vb;
2256 *yOddChromaDst1++ = Ud;
2257 *yOddChromaDst2++ = Vd;
2263 *uChromaDst1++ = Uc;
2264 *uChromaDst2++ = Vc;
2269 *vChromaDst1++ = Uc;
2270 *vChromaDst2++ = Vc;
2276void general_RGBToAVC444YUVv2_BGRX_DOUBLE_ROW(
2277 size_t offset,
const BYTE* WINPR_RESTRICT pSrcEven,
const BYTE* WINPR_RESTRICT pSrcOdd,
2278 BYTE* WINPR_RESTRICT yLumaDstEven, BYTE* WINPR_RESTRICT yLumaDstOdd,
2279 BYTE* WINPR_RESTRICT uLumaDst, BYTE* WINPR_RESTRICT vLumaDst,
2280 BYTE* WINPR_RESTRICT yEvenChromaDst1, BYTE* WINPR_RESTRICT yEvenChromaDst2,
2281 BYTE* WINPR_RESTRICT yOddChromaDst1, BYTE* WINPR_RESTRICT yOddChromaDst2,
2282 BYTE* WINPR_RESTRICT uChromaDst1, BYTE* WINPR_RESTRICT uChromaDst2,
2283 BYTE* WINPR_RESTRICT vChromaDst1, BYTE* WINPR_RESTRICT vChromaDst2, UINT32 width)
2285 int_general_RGBToAVC444YUVv2_BGRX_DOUBLE_ROW(
2286 offset, pSrcEven, pSrcOdd, yLumaDstEven, yLumaDstOdd, uLumaDst, vLumaDst, yEvenChromaDst1,
2287 yEvenChromaDst2, yOddChromaDst1, yOddChromaDst2, uChromaDst1, uChromaDst2, vChromaDst1,
2288 vChromaDst2, width);
2291static inline pstatus_t general_RGBToAVC444YUVv2_BGRX(
const BYTE* WINPR_RESTRICT pSrc,
2292 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst1[3],
2293 const UINT32 dst1Step[3],
2294 BYTE* WINPR_RESTRICT pDst2[3],
2295 const UINT32 dst2Step[3],
2298 if (roi->height < 1 || roi->width < 1)
2299 return !PRIMITIVES_SUCCESS;
2302 for (; y < roi->height - roi->height % 2; y += 2)
2304 const BYTE* srcEven = (pSrc + y * srcStep);
2305 const BYTE* srcOdd = (srcEven + srcStep);
2306 BYTE* dstLumaYEven = (pDst1[0] + y * dst1Step[0]);
2307 BYTE* dstLumaYOdd = (dstLumaYEven + dst1Step[0]);
2308 BYTE* dstLumaU = (pDst1[1] + (y / 2) * dst1Step[1]);
2309 BYTE* dstLumaV = (pDst1[2] + (y / 2) * dst1Step[2]);
2310 BYTE* dstEvenChromaY1 = (pDst2[0] + y * dst2Step[0]);
2311 BYTE* dstEvenChromaY2 = dstEvenChromaY1 + roi->width / 2;
2312 BYTE* dstOddChromaY1 = dstEvenChromaY1 + dst2Step[0];
2313 BYTE* dstOddChromaY2 = dstEvenChromaY2 + dst2Step[0];
2314 BYTE* dstChromaU1 = (pDst2[1] + (y / 2) * dst2Step[1]);
2315 BYTE* dstChromaV1 = (pDst2[2] + (y / 2) * dst2Step[2]);
2316 BYTE* dstChromaU2 = dstChromaU1 + roi->width / 4;
2317 BYTE* dstChromaV2 = dstChromaV1 + roi->width / 4;
2318 int_general_RGBToAVC444YUVv2_BGRX_DOUBLE_ROW(
2319 0, srcEven, srcOdd, dstLumaYEven, dstLumaYOdd, dstLumaU, dstLumaV, dstEvenChromaY1,
2320 dstEvenChromaY2, dstOddChromaY1, dstOddChromaY2, dstChromaU1, dstChromaU2, dstChromaV1,
2321 dstChromaV2, roi->width);
2323 for (; y < roi->height; y++)
2325 const BYTE* srcEven = (pSrc + y * srcStep);
2326 BYTE* dstLumaYEven = (pDst1[0] + y * dst1Step[0]);
2327 BYTE* dstLumaU = (pDst1[1] + (y / 2) * dst1Step[1]);
2328 BYTE* dstLumaV = (pDst1[2] + (y / 2) * dst1Step[2]);
2329 BYTE* dstEvenChromaY1 = (pDst2[0] + y * dst2Step[0]);
2330 BYTE* dstEvenChromaY2 = dstEvenChromaY1 + roi->width / 2;
2331 int_general_RGBToAVC444YUVv2_BGRX_DOUBLE_ROW(
2332 0, srcEven,
nullptr, dstLumaYEven,
nullptr, dstLumaU, dstLumaV, dstEvenChromaY1,
2333 dstEvenChromaY2,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, roi->width);
2336 return PRIMITIVES_SUCCESS;
2339static pstatus_t general_RGBToAVC444YUVv2(
const BYTE* WINPR_RESTRICT pSrc, UINT32 srcFormat,
2340 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst1[3],
2341 const UINT32 dst1Step[3], BYTE* WINPR_RESTRICT pDst2[3],
2342 const UINT32 dst2Step[3],
2347 case PIXEL_FORMAT_BGRA32:
2348 case PIXEL_FORMAT_BGRX32:
2349 return general_RGBToAVC444YUVv2_BGRX(pSrc, srcStep, pDst1, dst1Step, pDst2, dst2Step,
2353 return general_RGBToAVC444YUVv2_ANY(pSrc, srcFormat, srcStep, pDst1, dst1Step, pDst2,
2357 return !PRIMITIVES_SUCCESS;
2360void primitives_init_YUV(
primitives_t* WINPR_RESTRICT prims)
2362 prims->YUV420ToRGB_8u_P3AC4R = general_YUV420ToRGB_8u_P3AC4R;
2363 prims->YUV444ToRGB_8u_P3AC4R = general_YUV444ToRGB_8u_P3AC4R;
2364 prims->RGBToYUV420_8u_P3AC4R = general_RGBToYUV420_8u_P3AC4R;
2365 prims->RGBToYUV444_8u_P3AC4R = general_RGBToYUV444_8u_P3AC4R;
2366 prims->RGBToI444_8u = general_RGBToI444_8u;
2367 prims->YUV420CombineToYUV444 = general_YUV420CombineToYUV444;
2368 prims->YUV444SplitToYUV420 = general_YUV444SplitToYUV420;
2369 prims->RGBToAVC444YUV = general_RGBToAVC444YUV;
2370 prims->RGBToAVC444YUVv2 = general_RGBToAVC444YUVv2;
2373void primitives_init_YUV_opt(
primitives_t* WINPR_RESTRICT prims)
2375 primitives_init_YUV(prims);
2376 primitives_init_YUV_sse41(prims);
2377 primitives_init_YUV_neon(prims);