1#include <winpr/sysinfo.h>
2#include <winpr/assert.h>
6#include <freerdp/settings.h>
7#include <freerdp/codec/region.h>
8#include <freerdp/primitives.h>
9#include <freerdp/log.h>
10#include <freerdp/codec/yuv.h>
12#define TAG FREERDP_TAG("codec")
19 const BYTE* pYUVData[3];
25} YUV_PROCESS_WORK_PARAM;
30 const BYTE* pYUVData[3];
35 avc444_frame_type type;
36} YUV_COMBINE_WORK_PARAM;
48 BYTE* pYUVLumaData[3];
49 BYTE* pYUVChromaData[3];
51} YUV_ENCODE_WORK_PARAM;
60 UINT32 work_object_count;
61 PTP_WORK* work_objects;
62 YUV_ENCODE_WORK_PARAM* work_enc_params;
63 YUV_PROCESS_WORK_PARAM* work_dec_params;
64 YUV_COMBINE_WORK_PARAM* work_combined_params;
67static inline BOOL avc420_yuv_to_rgb(
const BYTE* WINPR_RESTRICT pYUVData[3],
68 const UINT32 iStride[3],
69 const RECTANGLE_16* WINPR_RESTRICT rect, UINT32 nDstStep,
70 BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat)
74 const BYTE* pYUVPoint[3];
76 WINPR_ASSERT(pYUVData);
77 WINPR_ASSERT(iStride);
79 WINPR_ASSERT(pDstData);
81 const INT32 width = rect->right - rect->left;
82 const INT32 height = rect->bottom - rect->top;
83 BYTE* pDstPoint = pDstData + 1ULL * rect->top * nDstStep +
84 1ULL * rect->left * FreeRDPGetBytesPerPixel(DstFormat);
86 pYUVPoint[0] = pYUVData[0] + 1ULL * rect->top * iStride[0] + rect->left;
87 pYUVPoint[1] = pYUVData[1] + 1ULL * rect->top / 2 * iStride[1] + rect->left / 2;
88 pYUVPoint[2] = pYUVData[2] + 1ULL * rect->top / 2 * iStride[2] + rect->left / 2;
90 roi.width = WINPR_ASSERTING_INT_CAST(uint32_t, width);
91 roi.height = WINPR_ASSERTING_INT_CAST(uint32_t, height);
93 return (prims->YUV420ToRGB_8u_P3AC4R(pYUVPoint, iStride, pDstPoint, nDstStep, DstFormat,
94 &roi) == PRIMITIVES_SUCCESS);
97static inline BOOL avc444_yuv_to_rgb(
const BYTE* WINPR_RESTRICT pYUVData[3],
98 const UINT32 iStride[3],
99 const RECTANGLE_16* WINPR_RESTRICT rect, UINT32 nDstStep,
100 BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat)
104 const BYTE* pYUVPoint[3];
106 WINPR_ASSERT(pYUVData);
107 WINPR_ASSERT(iStride);
109 WINPR_ASSERT(pDstData);
111 const INT32 width = rect->right - rect->left;
112 const INT32 height = rect->bottom - rect->top;
113 BYTE* pDstPoint = pDstData + 1ULL * rect->top * nDstStep +
114 1ULL * rect->left * FreeRDPGetBytesPerPixel(DstFormat);
116 pYUVPoint[0] = pYUVData[0] + 1ULL * rect->top * iStride[0] + rect->left;
117 pYUVPoint[1] = pYUVData[1] + 1ULL * rect->top * iStride[1] + rect->left;
118 pYUVPoint[2] = pYUVData[2] + 1ULL * rect->top * iStride[2] + rect->left;
120 roi.width = WINPR_ASSERTING_INT_CAST(uint32_t, width);
121 roi.height = WINPR_ASSERTING_INT_CAST(uint32_t, height);
123 return (prims->YUV444ToRGB_8u_P3AC4R(pYUVPoint, iStride, pDstPoint, nDstStep, DstFormat,
124 &roi) == PRIMITIVES_SUCCESS);
127static void CALLBACK yuv420_process_work_callback(PTP_CALLBACK_INSTANCE instance,
void* context,
130 YUV_PROCESS_WORK_PARAM* param = (YUV_PROCESS_WORK_PARAM*)context;
131 WINPR_UNUSED(instance);
135 if (!avc420_yuv_to_rgb(param->pYUVData, param->iStride, ¶m->rect, param->nDstStep,
136 param->dest, param->DstFormat))
137 WLog_WARN(TAG,
"avc420_yuv_to_rgb failed");
140static void CALLBACK yuv444_process_work_callback(PTP_CALLBACK_INSTANCE instance,
void* context,
143 YUV_PROCESS_WORK_PARAM* param = (YUV_PROCESS_WORK_PARAM*)context;
144 WINPR_UNUSED(instance);
148 if (!avc444_yuv_to_rgb(param->pYUVData, param->iStride, ¶m->rect, param->nDstStep,
149 param->dest, param->DstFormat))
150 WLog_WARN(TAG,
"avc444_yuv_to_rgb failed");
153BOOL yuv_context_reset(YUV_CONTEXT* WINPR_RESTRICT context, UINT32 width, UINT32 height)
156 WINPR_ASSERT(context);
158 context->width = width;
159 context->height = height;
161 context->heightStep = height;
163 if (context->useThreads)
165 context->heightStep = 16;
171 const size_t pw = (width + TILE_SIZE - width % TILE_SIZE) / 16;
172 const size_t ph = (height + TILE_SIZE - height % TILE_SIZE) / 16;
174 const size_t count = pw * ph;
176 context->work_object_count = 0;
177 if (context->encoder)
179 void* tmp = winpr_aligned_recalloc(context->work_enc_params, count,
180 sizeof(YUV_ENCODE_WORK_PARAM), 32);
183 memset(tmp, 0, count *
sizeof(YUV_ENCODE_WORK_PARAM));
185 context->work_enc_params = tmp;
189 void* tmp = winpr_aligned_recalloc(context->work_dec_params, count,
190 sizeof(YUV_PROCESS_WORK_PARAM), 32);
193 memset(tmp, 0, count *
sizeof(YUV_PROCESS_WORK_PARAM));
195 context->work_dec_params = tmp;
197 void* ctmp = winpr_aligned_recalloc(context->work_combined_params, count,
198 sizeof(YUV_COMBINE_WORK_PARAM), 32);
201 memset(ctmp, 0, count *
sizeof(YUV_COMBINE_WORK_PARAM));
203 context->work_combined_params = ctmp;
207 winpr_aligned_recalloc((
void*)context->work_objects, count,
sizeof(PTP_WORK), 32);
210 memset(wtmp, 0, count *
sizeof(PTP_WORK));
212 context->work_objects = (PTP_WORK*)wtmp;
213 context->work_object_count = WINPR_ASSERTING_INT_CAST(uint32_t, count);
220YUV_CONTEXT* yuv_context_new(BOOL encoder, UINT32 ThreadingFlags)
224 if (!primitives_get())
227 YUV_CONTEXT* ret = winpr_aligned_calloc(1,
sizeof(*ret), 32);
231 ret->encoder = encoder;
232 if (!(ThreadingFlags & THREADING_FLAGS_DISABLE_THREADS))
234 GetNativeSystemInfo(&sysInfos);
235 ret->useThreads = (sysInfos.dwNumberOfProcessors > 1);
241void yuv_context_free(YUV_CONTEXT* context)
245 if (context->useThreads)
247 winpr_aligned_free((
void*)context->work_objects);
248 winpr_aligned_free(context->work_combined_params);
249 winpr_aligned_free(context->work_enc_params);
250 winpr_aligned_free(context->work_dec_params);
252 winpr_aligned_free(context);
255static inline YUV_PROCESS_WORK_PARAM pool_decode_param(
const RECTANGLE_16* WINPR_RESTRICT rect,
256 YUV_CONTEXT* WINPR_RESTRICT context,
257 const BYTE* WINPR_RESTRICT pYUVData[3],
258 const UINT32 iStride[3], UINT32 DstFormat,
259 BYTE* WINPR_RESTRICT dest, UINT32 nDstStep)
261 YUV_PROCESS_WORK_PARAM current = WINPR_C_ARRAY_INIT;
264 WINPR_ASSERT(context);
265 WINPR_ASSERT(pYUVData);
266 WINPR_ASSERT(iStride);
269 current.context = context;
270 current.DstFormat = DstFormat;
271 current.pYUVData[0] = pYUVData[0];
272 current.pYUVData[1] = pYUVData[1];
273 current.pYUVData[2] = pYUVData[2];
274 current.iStride[0] = iStride[0];
275 current.iStride[1] = iStride[1];
276 current.iStride[2] = iStride[2];
277 current.nDstStep = nDstStep;
279 current.rect = *rect;
283static BOOL submit_object(PTP_WORK* WINPR_RESTRICT work_object, PTP_WORK_CALLBACK cb,
284 const void* WINPR_RESTRICT param, YUV_CONTEXT* WINPR_RESTRICT context)
297 *work_object =
nullptr;
299 if (!param || !context)
302 *work_object = CreateThreadpoolWork(cb, cnv.pv,
nullptr);
306 SubmitThreadpoolWork(*work_object);
310static void free_objects(PTP_WORK* work_objects, UINT32 waitCount)
312 WINPR_ASSERT(work_objects || (waitCount == 0));
314 for (UINT32 i = 0; i < waitCount; i++)
316 PTP_WORK cur = work_objects[i];
317 work_objects[i] =
nullptr;
322 WaitForThreadpoolWorkCallbacks(cur, FALSE);
323 CloseThreadpoolWork(cur);
327static BOOL intersects(UINT32 pos,
const RECTANGLE_16* WINPR_RESTRICT regionRects,
328 UINT32 numRegionRects)
330 WINPR_ASSERT(regionRects || (numRegionRects == 0));
332 for (UINT32 x = pos + 1; x < numRegionRects; x++)
337 if (rectangles_intersects(what, rect))
339 WLog_WARN(TAG,
"YUV decoder: intersecting rectangles, aborting");
347static RECTANGLE_16 clamp(YUV_CONTEXT* WINPR_RESTRICT context,
348 const RECTANGLE_16* WINPR_RESTRICT rect, UINT32 srcHeight)
350 WINPR_ASSERT(context);
354 const UINT32 height = MIN(context->height, srcHeight);
356 c.top = WINPR_ASSERTING_INT_CAST(UINT16, height);
357 if (c.bottom > height)
358 c.bottom = WINPR_ASSERTING_INT_CAST(UINT16, height);
362static BOOL pool_decode(YUV_CONTEXT* WINPR_RESTRICT context, PTP_WORK_CALLBACK cb,
363 const BYTE* WINPR_RESTRICT pYUVData[3],
const UINT32 iStride[3],
364 UINT32 yuvHeight, UINT32 DstFormat, BYTE* WINPR_RESTRICT dest,
365 UINT32 nDstStep,
const RECTANGLE_16* WINPR_RESTRICT regionRects,
366 UINT32 numRegionRects)
369 UINT32 waitCount = 0;
372 WINPR_ASSERT(context);
374 WINPR_ASSERT(pYUVData);
375 WINPR_ASSERT(iStride);
377 WINPR_ASSERT(regionRects || (numRegionRects == 0));
379 if (context->encoder)
381 WLog_ERR(TAG,
"YUV context set up for encoding, can not decode with it, aborting");
385 if (!context->useThreads || (primitives_flags(prims) & PRIM_FLAGS_HAVE_EXTGPU))
387 for (UINT32 y = 0; y < numRegionRects; y++)
389 const RECTANGLE_16 rect = clamp(context, ®ionRects[y], yuvHeight);
390 YUV_PROCESS_WORK_PARAM current =
391 pool_decode_param(&rect, context, pYUVData, iStride, DstFormat, dest, nDstStep);
392 cb(
nullptr, ¤t,
nullptr);
398 for (UINT32 x = 0; x < numRegionRects; x++)
400 RECTANGLE_16 r = clamp(context, ®ionRects[x], yuvHeight);
402 if (intersects(x, regionRects, numRegionRects))
405 while (r.left < r.right)
408 y.right = MIN(r.right, r.left + TILE_SIZE);
410 while (y.top < y.bottom)
414 if (context->work_object_count <= waitCount)
416 free_objects(context->work_objects, context->work_object_count);
420 YUV_PROCESS_WORK_PARAM* cur = &context->work_dec_params[waitCount];
421 z.bottom = MIN(z.bottom, z.top + TILE_SIZE);
422 if (rectangle_is_empty(&z))
424 *cur = pool_decode_param(&z, context, pYUVData, iStride, DstFormat, dest, nDstStep);
425 if (!submit_object(&context->work_objects[waitCount], cb, cur, context))
436 free_objects(context->work_objects, context->work_object_count);
440static inline BOOL check_rect(
const YUV_CONTEXT* WINPR_RESTRICT yuv,
441 const RECTANGLE_16* WINPR_RESTRICT rect, UINT32 nDstWidth,
448 if ((rect->right > yuv->width) || (rect->left > yuv->width))
451 if ((rect->top > yuv->height) || (rect->bottom > yuv->height))
455 if ((rect->right > nDstWidth) || (rect->left > nDstWidth))
458 if ((rect->bottom > nDstHeight) || (rect->top > nDstHeight))
464static void CALLBACK yuv444_combine_work_callback(PTP_CALLBACK_INSTANCE instance,
void* context,
467 YUV_COMBINE_WORK_PARAM* param = (YUV_COMBINE_WORK_PARAM*)context;
471 YUV_CONTEXT* yuv = param->context;
481 const UINT32 alignedWidth =
482 MIN(yuv->width + ((yuv->width % 32 != 0) ? 32 - yuv->width % 32 : 0), param->iStride[0]);
483 const UINT32 alignedHeight =
484 yuv->height + ((yuv->height % 16 != 0) ? 16 - yuv->height % 16 : 0);
486 WINPR_UNUSED(instance);
489 if (!check_rect(param->context, rect, yuv->width, yuv->height))
492 if (prims->YUV420CombineToYUV444(param->type, param->pYUVData, param->iStride, alignedWidth,
493 alignedHeight, param->pYUVDstData, param->iDstStride,
494 rect) != PRIMITIVES_SUCCESS)
495 WLog_WARN(TAG,
"YUV420CombineToYUV444 failed");
498static inline YUV_COMBINE_WORK_PARAM
499pool_decode_rect_param(
const RECTANGLE_16* WINPR_RESTRICT rect, YUV_CONTEXT* WINPR_RESTRICT context,
500 BYTE type,
const BYTE* WINPR_RESTRICT pYUVData[3],
const UINT32 iStride[3],
501 BYTE* WINPR_RESTRICT pYUVDstData[3],
const UINT32 iDstStride[3])
503 YUV_COMBINE_WORK_PARAM current = WINPR_C_ARRAY_INIT;
506 WINPR_ASSERT(context);
507 WINPR_ASSERT(pYUVData);
508 WINPR_ASSERT(iStride);
509 WINPR_ASSERT(pYUVDstData);
510 WINPR_ASSERT(iDstStride);
512 current.context = context;
513 current.pYUVData[0] = pYUVData[0];
514 current.pYUVData[1] = pYUVData[1];
515 current.pYUVData[2] = pYUVData[2];
516 current.pYUVDstData[0] = pYUVDstData[0];
517 current.pYUVDstData[1] = pYUVDstData[1];
518 current.pYUVDstData[2] = pYUVDstData[2];
519 current.iStride[0] = iStride[0];
520 current.iStride[1] = iStride[1];
521 current.iStride[2] = iStride[2];
522 current.iDstStride[0] = iDstStride[0];
523 current.iDstStride[1] = iDstStride[1];
524 current.iDstStride[2] = iDstStride[2];
525 current.type = WINPR_ASSERTING_INT_CAST(avc444_frame_type, type);
526 current.rect = *rect;
530static BOOL pool_decode_rect(YUV_CONTEXT* WINPR_RESTRICT context, BYTE type,
531 const BYTE* WINPR_RESTRICT pYUVData[3],
const UINT32 iStride[3],
532 BYTE* WINPR_RESTRICT pYUVDstData[3],
const UINT32 iDstStride[3],
533 const RECTANGLE_16* WINPR_RESTRICT regionRects, UINT32 numRegionRects)
536 UINT32 waitCount = 0;
537 PTP_WORK_CALLBACK cb = yuv444_combine_work_callback;
540 WINPR_ASSERT(context);
541 WINPR_ASSERT(pYUVData);
542 WINPR_ASSERT(iStride);
543 WINPR_ASSERT(pYUVDstData);
544 WINPR_ASSERT(iDstStride);
545 WINPR_ASSERT(regionRects || (numRegionRects == 0));
547 if (!context->useThreads || (primitives_flags(prims) & PRIM_FLAGS_HAVE_EXTGPU))
549 for (UINT32 y = 0; y < numRegionRects; y++)
551 YUV_COMBINE_WORK_PARAM current = pool_decode_rect_param(
552 ®ionRects[y], context, type, pYUVData, iStride, pYUVDstData, iDstStride);
553 cb(
nullptr, ¤t,
nullptr);
559 for (waitCount = 0; waitCount < numRegionRects; waitCount++)
561 YUV_COMBINE_WORK_PARAM* current =
nullptr;
563 if (context->work_object_count <= waitCount)
565 free_objects(context->work_objects, context->work_object_count);
568 current = &context->work_combined_params[waitCount];
569 *current = pool_decode_rect_param(®ionRects[waitCount], context, type, pYUVData, iStride,
570 pYUVDstData, iDstStride);
572 if (!submit_object(&context->work_objects[waitCount], cb, current, context))
578 free_objects(context->work_objects, context->work_object_count);
582BOOL yuv444_context_decode(YUV_CONTEXT* WINPR_RESTRICT context, BYTE type,
583 const BYTE* WINPR_RESTRICT pYUVData[3],
const UINT32 iStride[3],
584 UINT32 srcYuvHeight, BYTE* WINPR_RESTRICT pYUVDstData[3],
585 const UINT32 iDstStride[3], DWORD DstFormat, BYTE* WINPR_RESTRICT dest,
586 UINT32 nDstStep,
const RECTANGLE_16* WINPR_RESTRICT regionRects,
587 UINT32 numRegionRects)
589 const BYTE* pYUVCDstData[3];
591 WINPR_ASSERT(context);
592 WINPR_ASSERT(pYUVData);
593 WINPR_ASSERT(iStride);
594 WINPR_ASSERT(pYUVDstData);
595 WINPR_ASSERT(iDstStride);
597 WINPR_ASSERT(regionRects || (numRegionRects == 0));
599 if (context->encoder)
601 WLog_ERR(TAG,
"YUV context set up for encoding, can not decode with it, aborting");
604 if (!pool_decode_rect(context, type, pYUVData, iStride, pYUVDstData, iDstStride, regionRects,
608 pYUVCDstData[0] = pYUVDstData[0];
609 pYUVCDstData[1] = pYUVDstData[1];
610 pYUVCDstData[2] = pYUVDstData[2];
611 return pool_decode(context, yuv444_process_work_callback, pYUVCDstData, iDstStride,
612 srcYuvHeight, DstFormat, dest, nDstStep, regionRects, numRegionRects);
615BOOL yuv420_context_decode(YUV_CONTEXT* WINPR_RESTRICT context,
616 const BYTE* WINPR_RESTRICT pYUVData[3],
const UINT32 iStride[3],
617 UINT32 yuvHeight, DWORD DstFormat, BYTE* WINPR_RESTRICT dest,
618 UINT32 nDstStep,
const RECTANGLE_16* WINPR_RESTRICT regionRects,
619 UINT32 numRegionRects)
621 return pool_decode(context, yuv420_process_work_callback, pYUVData, iStride, yuvHeight,
622 DstFormat, dest, nDstStep, regionRects, numRegionRects);
625static void CALLBACK yuv420_encode_work_callback(PTP_CALLBACK_INSTANCE instance,
void* context,
629 YUV_ENCODE_WORK_PARAM* param = (YUV_ENCODE_WORK_PARAM*)context;
632 const BYTE* src =
nullptr;
634 WINPR_UNUSED(instance);
638 roi.width = param->rect.right - param->rect.left;
639 roi.height = param->rect.bottom - param->rect.top;
640 src = param->pSrcData + 1ULL * param->nSrcStep * param->rect.top +
641 1ULL * param->rect.left * FreeRDPGetBytesPerPixel(param->SrcFormat);
643 param->pYUVLumaData[0] + 1ULL * param->rect.top * param->iStride[0] + param->rect.left;
644 pYUVData[1] = param->pYUVLumaData[1] + 1ULL * param->rect.top / 2 * param->iStride[1] +
645 param->rect.left / 2;
646 pYUVData[2] = param->pYUVLumaData[2] + 1ULL * param->rect.top / 2 * param->iStride[2] +
647 param->rect.left / 2;
649 if (prims->RGBToYUV420_8u_P3AC4R(src, param->SrcFormat, param->nSrcStep, pYUVData,
650 param->iStride, &roi) != PRIMITIVES_SUCCESS)
652 WLog_ERR(TAG,
"error when decoding lines");
656static void CALLBACK yuv444v1_encode_work_callback(PTP_CALLBACK_INSTANCE instance,
void* context,
660 YUV_ENCODE_WORK_PARAM* param = (YUV_ENCODE_WORK_PARAM*)context;
662 BYTE* pYUVLumaData[3];
663 BYTE* pYUVChromaData[3];
664 const BYTE* src =
nullptr;
666 WINPR_UNUSED(instance);
670 roi.width = param->rect.right - param->rect.left;
671 roi.height = param->rect.bottom - param->rect.top;
672 src = param->pSrcData + 1ULL * param->nSrcStep * param->rect.top +
673 1ULL * param->rect.left * FreeRDPGetBytesPerPixel(param->SrcFormat);
675 param->pYUVLumaData[0] + 1ULL * param->rect.top * param->iStride[0] + param->rect.left;
676 pYUVLumaData[1] = param->pYUVLumaData[1] + 1ULL * param->rect.top / 2 * param->iStride[1] +
677 param->rect.left / 2;
678 pYUVLumaData[2] = param->pYUVLumaData[2] + 1ULL * param->rect.top / 2 * param->iStride[2] +
679 param->rect.left / 2;
681 param->pYUVChromaData[0] + 1ULL * param->rect.top * param->iStride[0] + param->rect.left;
682 pYUVChromaData[1] = param->pYUVChromaData[1] + 1ULL * param->rect.top / 2 * param->iStride[1] +
683 param->rect.left / 2;
684 pYUVChromaData[2] = param->pYUVChromaData[2] + 1ULL * param->rect.top / 2 * param->iStride[2] +
685 param->rect.left / 2;
686 if (prims->RGBToAVC444YUV(src, param->SrcFormat, param->nSrcStep, pYUVLumaData, param->iStride,
687 pYUVChromaData, param->iStride, &roi) != PRIMITIVES_SUCCESS)
689 WLog_ERR(TAG,
"error when decoding lines");
693static void CALLBACK yuv444v2_encode_work_callback(PTP_CALLBACK_INSTANCE instance,
void* context,
697 YUV_ENCODE_WORK_PARAM* param = (YUV_ENCODE_WORK_PARAM*)context;
699 BYTE* pYUVLumaData[3];
700 BYTE* pYUVChromaData[3];
701 const BYTE* src =
nullptr;
703 WINPR_UNUSED(instance);
707 roi.width = param->rect.right - param->rect.left;
708 roi.height = param->rect.bottom - param->rect.top;
709 src = param->pSrcData + 1ULL * param->nSrcStep * param->rect.top +
710 1ULL * param->rect.left * FreeRDPGetBytesPerPixel(param->SrcFormat);
712 param->pYUVLumaData[0] + 1ULL * param->rect.top * param->iStride[0] + param->rect.left;
713 pYUVLumaData[1] = param->pYUVLumaData[1] + 1ULL * param->rect.top / 2 * param->iStride[1] +
714 param->rect.left / 2;
715 pYUVLumaData[2] = param->pYUVLumaData[2] + 1ULL * param->rect.top / 2 * param->iStride[2] +
716 param->rect.left / 2;
718 param->pYUVChromaData[0] + 1ULL * param->rect.top * param->iStride[0] + param->rect.left;
719 pYUVChromaData[1] = param->pYUVChromaData[1] + 1ULL * param->rect.top / 2 * param->iStride[1] +
720 param->rect.left / 2;
721 pYUVChromaData[2] = param->pYUVChromaData[2] + 1ULL * param->rect.top / 2 * param->iStride[2] +
722 param->rect.left / 2;
723 if (prims->RGBToAVC444YUVv2(src, param->SrcFormat, param->nSrcStep, pYUVLumaData,
724 param->iStride, pYUVChromaData, param->iStride,
725 &roi) != PRIMITIVES_SUCCESS)
727 WLog_ERR(TAG,
"error when decoding lines");
731static inline YUV_ENCODE_WORK_PARAM
732pool_encode_fill(
const RECTANGLE_16* WINPR_RESTRICT rect, YUV_CONTEXT* WINPR_RESTRICT context,
733 const BYTE* WINPR_RESTRICT pSrcData, UINT32 nSrcStep, UINT32 SrcFormat,
734 const UINT32 iStride[], BYTE* WINPR_RESTRICT pYUVLumaData[],
735 BYTE* WINPR_RESTRICT pYUVChromaData[])
737 YUV_ENCODE_WORK_PARAM current = WINPR_C_ARRAY_INIT;
740 WINPR_ASSERT(context);
741 WINPR_ASSERT(pSrcData);
742 WINPR_ASSERT(iStride);
743 WINPR_ASSERT(pYUVLumaData);
745 current.context = context;
746 current.pSrcData = pSrcData;
747 current.SrcFormat = SrcFormat;
748 current.nSrcStep = nSrcStep;
749 current.pYUVLumaData[0] = pYUVLumaData[0];
750 current.pYUVLumaData[1] = pYUVLumaData[1];
751 current.pYUVLumaData[2] = pYUVLumaData[2];
754 current.pYUVChromaData[0] = pYUVChromaData[0];
755 current.pYUVChromaData[1] = pYUVChromaData[1];
756 current.pYUVChromaData[2] = pYUVChromaData[2];
758 current.iStride[0] = iStride[0];
759 current.iStride[1] = iStride[1];
760 current.iStride[2] = iStride[2];
762 current.rect = *rect;
767static uint32_t getSteps(uint32_t height, uint32_t step)
769 const uint32_t steps = (height + step / 2 + 1) / step;
775static BOOL pool_encode(YUV_CONTEXT* WINPR_RESTRICT context, PTP_WORK_CALLBACK cb,
776 const BYTE* WINPR_RESTRICT pSrcData, UINT32 nSrcStep, UINT32 SrcFormat,
777 const UINT32 iStride[], BYTE* WINPR_RESTRICT pYUVLumaData[],
778 BYTE* WINPR_RESTRICT pYUVChromaData[],
779 const RECTANGLE_16* WINPR_RESTRICT regionRects, UINT32 numRegionRects)
783 UINT32 waitCount = 0;
785 WINPR_ASSERT(context);
787 WINPR_ASSERT(pSrcData);
788 WINPR_ASSERT(iStride);
789 WINPR_ASSERT(regionRects || (numRegionRects == 0));
791 if (!context->encoder)
794 WLog_ERR(TAG,
"YUV context set up for decoding, can not encode with it, aborting");
798 if (!context->useThreads || (primitives_flags(prims) & PRIM_FLAGS_HAVE_EXTGPU))
800 for (UINT32 x = 0; x < numRegionRects; x++)
802 YUV_ENCODE_WORK_PARAM current =
803 pool_encode_fill(®ionRects[x], context, pSrcData, nSrcStep, SrcFormat, iStride,
804 pYUVLumaData, pYUVChromaData);
805 cb(
nullptr, ¤t,
nullptr);
811 for (UINT32 x = 0; x < numRegionRects; x++)
814 const UINT32 height = rect->bottom - rect->top;
815 const UINT32 steps = getSteps(height, context->heightStep);
820 for (UINT32 x = 0; x < numRegionRects; x++)
823 const UINT32 height = rect->bottom - rect->top;
824 const UINT32 steps = getSteps(height, context->heightStep);
826 for (UINT32 y = 0; y < steps; y++)
829 YUV_ENCODE_WORK_PARAM* current =
nullptr;
831 if (context->work_object_count <= waitCount)
833 free_objects(context->work_objects, context->work_object_count);
837 current = &context->work_enc_params[waitCount];
838 r.top += y * context->heightStep;
839 *current = pool_encode_fill(&r, context, pSrcData, nSrcStep, SrcFormat, iStride,
840 pYUVLumaData, pYUVChromaData);
841 if (!submit_object(&context->work_objects[waitCount], cb, current, context))
849 free_objects(context->work_objects, context->work_object_count);
853BOOL yuv420_context_encode(YUV_CONTEXT* WINPR_RESTRICT context,
const BYTE* WINPR_RESTRICT pSrcData,
854 UINT32 nSrcStep, UINT32 SrcFormat,
const UINT32 iStride[3],
855 BYTE* WINPR_RESTRICT pYUVData[3],
856 const RECTANGLE_16* WINPR_RESTRICT regionRects, UINT32 numRegionRects)
858 if (!context || !pSrcData || !iStride || !pYUVData || !regionRects)
861 return pool_encode(context, yuv420_encode_work_callback, pSrcData, nSrcStep, SrcFormat, iStride,
862 pYUVData,
nullptr, regionRects, numRegionRects);
865BOOL yuv444_context_encode(YUV_CONTEXT* WINPR_RESTRICT context, BYTE version,
866 const BYTE* WINPR_RESTRICT pSrcData, UINT32 nSrcStep, UINT32 SrcFormat,
867 const UINT32 iStride[3], BYTE* WINPR_RESTRICT pYUVLumaData[3],
868 BYTE* WINPR_RESTRICT pYUVChromaData[3],
869 const RECTANGLE_16* WINPR_RESTRICT regionRects, UINT32 numRegionRects)
871 PTP_WORK_CALLBACK cb =
nullptr;
875 cb = yuv444v1_encode_work_callback;
878 cb = yuv444v2_encode_work_callback;
884 return pool_encode(context, cb, pSrcData, nSrcStep, SrcFormat, iStride, pYUVLumaData,
885 pYUVChromaData, regionRects, numRegionRects);