1 #include <winpr/sysinfo.h>
2 #include <winpr/assert.h>
3 #include <winpr/cast.h>
4 #include <winpr/pool.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];
36 } YUV_COMBINE_WORK_PARAM;
48 BYTE* pYUVLumaData[3];
49 BYTE* pYUVChromaData[3];
51 } YUV_ENCODE_WORK_PARAM;
64 UINT32 work_object_count;
65 PTP_WORK* work_objects;
66 YUV_ENCODE_WORK_PARAM* work_enc_params;
67 YUV_PROCESS_WORK_PARAM* work_dec_params;
68 YUV_COMBINE_WORK_PARAM* work_combined_params;
71 static INLINE BOOL avc420_yuv_to_rgb(
const BYTE* WINPR_RESTRICT pYUVData[3],
72 const UINT32 iStride[3],
73 const RECTANGLE_16* WINPR_RESTRICT rect, UINT32 nDstStep,
74 BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat)
78 const BYTE* pYUVPoint[3];
80 WINPR_ASSERT(pYUVData);
81 WINPR_ASSERT(iStride);
83 WINPR_ASSERT(pDstData);
85 const INT32 width = rect->right - rect->left;
86 const INT32 height = rect->bottom - rect->top;
87 BYTE* pDstPoint = pDstData + 1ULL * rect->top * nDstStep +
88 1ULL * rect->left * FreeRDPGetBytesPerPixel(DstFormat);
90 pYUVPoint[0] = pYUVData[0] + 1ULL * rect->top * iStride[0] + rect->left;
91 pYUVPoint[1] = pYUVData[1] + 1ULL * rect->top / 2 * iStride[1] + rect->left / 2;
92 pYUVPoint[2] = pYUVData[2] + 1ULL * rect->top / 2 * iStride[2] + rect->left / 2;
94 roi.width = WINPR_ASSERTING_INT_CAST(uint32_t, width);
95 roi.height = WINPR_ASSERTING_INT_CAST(uint32_t, height);
97 if (prims->YUV420ToRGB_8u_P3AC4R(pYUVPoint, iStride, pDstPoint, nDstStep, DstFormat, &roi) !=
104 static INLINE BOOL avc444_yuv_to_rgb(
const BYTE* WINPR_RESTRICT pYUVData[3],
105 const UINT32 iStride[3],
106 const RECTANGLE_16* WINPR_RESTRICT rect, UINT32 nDstStep,
107 BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat)
111 const BYTE* pYUVPoint[3];
113 WINPR_ASSERT(pYUVData);
114 WINPR_ASSERT(iStride);
116 WINPR_ASSERT(pDstData);
118 const INT32 width = rect->right - rect->left;
119 const INT32 height = rect->bottom - rect->top;
120 BYTE* pDstPoint = pDstData + 1ULL * rect->top * nDstStep +
121 1ULL * rect->left * FreeRDPGetBytesPerPixel(DstFormat);
123 pYUVPoint[0] = pYUVData[0] + 1ULL * rect->top * iStride[0] + rect->left;
124 pYUVPoint[1] = pYUVData[1] + 1ULL * rect->top * iStride[1] + rect->left;
125 pYUVPoint[2] = pYUVData[2] + 1ULL * rect->top * iStride[2] + rect->left;
127 roi.width = WINPR_ASSERTING_INT_CAST(uint32_t, width);
128 roi.height = WINPR_ASSERTING_INT_CAST(uint32_t, height);
130 if (prims->YUV444ToRGB_8u_P3AC4R(pYUVPoint, iStride, pDstPoint, nDstStep, DstFormat, &roi) !=
137 static void CALLBACK yuv420_process_work_callback(PTP_CALLBACK_INSTANCE instance,
void* context,
140 YUV_PROCESS_WORK_PARAM* param = (YUV_PROCESS_WORK_PARAM*)context;
141 WINPR_UNUSED(instance);
145 if (!avc420_yuv_to_rgb(param->pYUVData, param->iStride, ¶m->rect, param->nDstStep,
146 param->dest, param->DstFormat))
147 WLog_WARN(TAG,
"avc420_yuv_to_rgb failed");
150 static void CALLBACK yuv444_process_work_callback(PTP_CALLBACK_INSTANCE instance,
void* context,
153 YUV_PROCESS_WORK_PARAM* param = (YUV_PROCESS_WORK_PARAM*)context;
154 WINPR_UNUSED(instance);
158 if (!avc444_yuv_to_rgb(param->pYUVData, param->iStride, ¶m->rect, param->nDstStep,
159 param->dest, param->DstFormat))
160 WLog_WARN(TAG,
"avc444_yuv_to_rgb failed");
163 BOOL yuv_context_reset(YUV_CONTEXT* WINPR_RESTRICT context, UINT32 width, UINT32 height)
166 WINPR_ASSERT(context);
168 context->width = width;
169 context->height = height;
170 context->heightStep = (height / context->nthreads);
172 if (context->useThreads)
174 const UINT32 pw = (width + TILE_SIZE - width % TILE_SIZE) / TILE_SIZE;
175 const UINT32 ph = (height + TILE_SIZE - height % TILE_SIZE) / TILE_SIZE;
179 const UINT32 count = pw * ph * 16;
181 context->work_object_count = 0;
182 if (context->encoder)
184 void* tmp = winpr_aligned_recalloc(context->work_enc_params, count,
185 sizeof(YUV_ENCODE_WORK_PARAM), 32);
188 memset(tmp, 0, count *
sizeof(YUV_ENCODE_WORK_PARAM));
190 context->work_enc_params = tmp;
194 void* tmp = winpr_aligned_recalloc(context->work_dec_params, count,
195 sizeof(YUV_PROCESS_WORK_PARAM), 32);
198 memset(tmp, 0, count *
sizeof(YUV_PROCESS_WORK_PARAM));
200 context->work_dec_params = tmp;
202 void* ctmp = winpr_aligned_recalloc(context->work_combined_params, count,
203 sizeof(YUV_COMBINE_WORK_PARAM), 32);
206 memset(ctmp, 0, count *
sizeof(YUV_COMBINE_WORK_PARAM));
208 context->work_combined_params = ctmp;
212 winpr_aligned_recalloc((
void*)context->work_objects, count,
sizeof(PTP_WORK), 32);
215 memset(wtmp, 0, count *
sizeof(PTP_WORK));
217 context->work_objects = (PTP_WORK*)wtmp;
218 context->work_object_count = count;
225 YUV_CONTEXT* yuv_context_new(BOOL encoder, UINT32 ThreadingFlags)
228 YUV_CONTEXT* ret = winpr_aligned_calloc(1,
sizeof(*ret), 32);
235 ret->encoder = encoder;
237 if (!(ThreadingFlags & THREADING_FLAGS_DISABLE_THREADS))
239 GetNativeSystemInfo(&sysInfos);
240 ret->useThreads = (sysInfos.dwNumberOfProcessors > 1);
243 ret->nthreads = sysInfos.dwNumberOfProcessors;
244 ret->threadPool = CreateThreadpool(NULL);
245 if (!ret->threadPool)
247 goto error_threadpool;
250 InitializeThreadpoolEnvironment(&ret->ThreadPoolEnv);
251 SetThreadpoolCallbackPool(&ret->ThreadPoolEnv, ret->threadPool);
258 WINPR_PRAGMA_DIAG_PUSH
259 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
260 yuv_context_free(ret);
261 WINPR_PRAGMA_DIAG_POP
265 void yuv_context_free(YUV_CONTEXT* context)
269 if (context->useThreads)
271 if (context->threadPool)
272 CloseThreadpool(context->threadPool);
273 DestroyThreadpoolEnvironment(&context->ThreadPoolEnv);
274 winpr_aligned_free((
void*)context->work_objects);
275 winpr_aligned_free(context->work_combined_params);
276 winpr_aligned_free(context->work_enc_params);
277 winpr_aligned_free(context->work_dec_params);
279 winpr_aligned_free(context);
282 static INLINE YUV_PROCESS_WORK_PARAM pool_decode_param(
const RECTANGLE_16* WINPR_RESTRICT rect,
283 YUV_CONTEXT* WINPR_RESTRICT context,
284 const BYTE* WINPR_RESTRICT pYUVData[3],
285 const UINT32 iStride[3], UINT32 DstFormat,
286 BYTE* WINPR_RESTRICT dest, UINT32 nDstStep)
288 YUV_PROCESS_WORK_PARAM current = { 0 };
291 WINPR_ASSERT(context);
292 WINPR_ASSERT(pYUVData);
293 WINPR_ASSERT(iStride);
296 current.context = context;
297 current.DstFormat = DstFormat;
298 current.pYUVData[0] = pYUVData[0];
299 current.pYUVData[1] = pYUVData[1];
300 current.pYUVData[2] = pYUVData[2];
301 current.iStride[0] = iStride[0];
302 current.iStride[1] = iStride[1];
303 current.iStride[2] = iStride[2];
304 current.nDstStep = nDstStep;
306 current.rect = *rect;
310 static BOOL submit_object(PTP_WORK* WINPR_RESTRICT work_object, PTP_WORK_CALLBACK cb,
311 const void* WINPR_RESTRICT param, YUV_CONTEXT* WINPR_RESTRICT context)
326 if (!param || !context)
329 *work_object = CreateThreadpoolWork(cb, cnv.pv, &context->ThreadPoolEnv);
333 SubmitThreadpoolWork(*work_object);
337 static void free_objects(PTP_WORK* work_objects, UINT32 waitCount)
339 WINPR_ASSERT(work_objects || (waitCount == 0));
341 for (UINT32 i = 0; i < waitCount; i++)
343 PTP_WORK cur = work_objects[i];
344 work_objects[i] = NULL;
349 WaitForThreadpoolWorkCallbacks(cur, FALSE);
350 CloseThreadpoolWork(cur);
354 static BOOL intersects(UINT32 pos,
const RECTANGLE_16* WINPR_RESTRICT regionRects,
355 UINT32 numRegionRects)
357 WINPR_ASSERT(regionRects || (numRegionRects == 0));
359 for (UINT32 x = pos + 1; x < numRegionRects; x++)
364 if (rectangles_intersects(what, rect))
366 WLog_WARN(TAG,
"YUV decoder: intersecting rectangles, aborting");
374 static RECTANGLE_16 clamp(YUV_CONTEXT* WINPR_RESTRICT context,
375 const RECTANGLE_16* WINPR_RESTRICT rect, UINT32 srcHeight)
377 WINPR_ASSERT(context);
381 const UINT32 height = MIN(context->height, srcHeight);
383 c.top = WINPR_ASSERTING_INT_CAST(UINT16, height);
384 if (c.bottom > height)
385 c.bottom = WINPR_ASSERTING_INT_CAST(UINT16, height);
389 static BOOL pool_decode(YUV_CONTEXT* WINPR_RESTRICT context, PTP_WORK_CALLBACK cb,
390 const BYTE* WINPR_RESTRICT pYUVData[3],
const UINT32 iStride[3],
391 UINT32 yuvHeight, UINT32 DstFormat, BYTE* WINPR_RESTRICT dest,
392 UINT32 nDstStep,
const RECTANGLE_16* WINPR_RESTRICT regionRects,
393 UINT32 numRegionRects)
396 UINT32 waitCount = 0;
399 WINPR_ASSERT(context);
401 WINPR_ASSERT(pYUVData);
402 WINPR_ASSERT(iStride);
404 WINPR_ASSERT(regionRects || (numRegionRects == 0));
406 if (context->encoder)
408 WLog_ERR(TAG,
"YUV context set up for encoding, can not decode with it, aborting");
412 if (!context->useThreads || (primitives_flags(prims) & PRIM_FLAGS_HAVE_EXTGPU))
414 for (UINT32 y = 0; y < numRegionRects; y++)
416 const RECTANGLE_16 rect = clamp(context, ®ionRects[y], yuvHeight);
417 YUV_PROCESS_WORK_PARAM current =
418 pool_decode_param(&rect, context, pYUVData, iStride, DstFormat, dest, nDstStep);
419 cb(NULL, ¤t, NULL);
425 for (UINT32 x = 0; x < numRegionRects; x++)
427 RECTANGLE_16 r = clamp(context, ®ionRects[x], yuvHeight);
429 if (intersects(x, regionRects, numRegionRects))
432 while (r.left < r.right)
435 y.right = MIN(r.right, r.left + TILE_SIZE);
437 while (y.top < y.bottom)
441 if (context->work_object_count <= waitCount)
444 "YUV decoder: invalid number of tiles, only support less than %" PRIu32
446 context->work_object_count, waitCount);
450 YUV_PROCESS_WORK_PARAM* cur = &context->work_dec_params[waitCount];
451 z.bottom = MIN(z.bottom, z.top + TILE_SIZE);
452 if (rectangle_is_empty(&z))
454 *cur = pool_decode_param(&z, context, pYUVData, iStride, DstFormat, dest, nDstStep);
455 if (!submit_object(&context->work_objects[waitCount], cb, cur, context))
466 free_objects(context->work_objects, context->work_object_count);
470 static INLINE BOOL check_rect(
const YUV_CONTEXT* WINPR_RESTRICT yuv,
471 const RECTANGLE_16* WINPR_RESTRICT rect, UINT32 nDstWidth,
478 if ((rect->right > yuv->width) || (rect->left > yuv->width))
481 if ((rect->top > yuv->height) || (rect->bottom > yuv->height))
485 if ((rect->right > nDstWidth) || (rect->left > nDstWidth))
488 if ((rect->bottom > nDstHeight) || (rect->top > nDstHeight))
494 static void CALLBACK yuv444_combine_work_callback(PTP_CALLBACK_INSTANCE instance,
void* context,
497 YUV_COMBINE_WORK_PARAM* param = (YUV_COMBINE_WORK_PARAM*)context;
501 YUV_CONTEXT* yuv = param->context;
507 const UINT32 alignedWidth = yuv->width + ((yuv->width % 16 != 0) ? 16 - yuv->width % 16 : 0);
508 const UINT32 alignedHeight =
509 yuv->height + ((yuv->height % 16 != 0) ? 16 - yuv->height % 16 : 0);
511 WINPR_UNUSED(instance);
514 if (!check_rect(param->context, rect, yuv->width, yuv->height))
517 if (prims->YUV420CombineToYUV444(param->type, param->pYUVData, param->iStride, alignedWidth,
518 alignedHeight, param->pYUVDstData, param->iDstStride,
519 rect) != PRIMITIVES_SUCCESS)
520 WLog_WARN(TAG,
"YUV420CombineToYUV444 failed");
523 static INLINE YUV_COMBINE_WORK_PARAM
524 pool_decode_rect_param(
const RECTANGLE_16* WINPR_RESTRICT rect, YUV_CONTEXT* WINPR_RESTRICT context,
525 BYTE type,
const BYTE* WINPR_RESTRICT pYUVData[3],
const UINT32 iStride[3],
526 BYTE* WINPR_RESTRICT pYUVDstData[3],
const UINT32 iDstStride[3])
528 YUV_COMBINE_WORK_PARAM current = { 0 };
531 WINPR_ASSERT(context);
532 WINPR_ASSERT(pYUVData);
533 WINPR_ASSERT(iStride);
534 WINPR_ASSERT(pYUVDstData);
535 WINPR_ASSERT(iDstStride);
537 current.context = context;
538 current.pYUVData[0] = pYUVData[0];
539 current.pYUVData[1] = pYUVData[1];
540 current.pYUVData[2] = pYUVData[2];
541 current.pYUVDstData[0] = pYUVDstData[0];
542 current.pYUVDstData[1] = pYUVDstData[1];
543 current.pYUVDstData[2] = pYUVDstData[2];
544 current.iStride[0] = iStride[0];
545 current.iStride[1] = iStride[1];
546 current.iStride[2] = iStride[2];
547 current.iDstStride[0] = iDstStride[0];
548 current.iDstStride[1] = iDstStride[1];
549 current.iDstStride[2] = iDstStride[2];
551 current.rect = *rect;
555 static BOOL pool_decode_rect(YUV_CONTEXT* WINPR_RESTRICT context, BYTE type,
556 const BYTE* WINPR_RESTRICT pYUVData[3],
const UINT32 iStride[3],
557 BYTE* WINPR_RESTRICT pYUVDstData[3],
const UINT32 iDstStride[3],
558 const RECTANGLE_16* WINPR_RESTRICT regionRects, UINT32 numRegionRects)
561 UINT32 waitCount = 0;
562 PTP_WORK_CALLBACK cb = yuv444_combine_work_callback;
565 WINPR_ASSERT(context);
566 WINPR_ASSERT(pYUVData);
567 WINPR_ASSERT(iStride);
568 WINPR_ASSERT(pYUVDstData);
569 WINPR_ASSERT(iDstStride);
570 WINPR_ASSERT(regionRects || (numRegionRects == 0));
572 if (!context->useThreads || (primitives_flags(prims) & PRIM_FLAGS_HAVE_EXTGPU))
574 for (UINT32 y = 0; y < numRegionRects; y++)
576 YUV_COMBINE_WORK_PARAM current = pool_decode_rect_param(
577 ®ionRects[y], context, type, pYUVData, iStride, pYUVDstData, iDstStride);
578 cb(NULL, ¤t, NULL);
584 for (waitCount = 0; waitCount < numRegionRects; waitCount++)
586 YUV_COMBINE_WORK_PARAM* current = NULL;
588 if (context->work_object_count <= waitCount)
591 "YUV rect decoder: invalid number of tiles, only support less than %" PRIu32
593 context->work_object_count, waitCount);
596 current = &context->work_combined_params[waitCount];
597 *current = pool_decode_rect_param(®ionRects[waitCount], context, type, pYUVData, iStride,
598 pYUVDstData, iDstStride);
600 if (!submit_object(&context->work_objects[waitCount], cb, current, context))
606 free_objects(context->work_objects, context->work_object_count);
610 BOOL yuv444_context_decode(YUV_CONTEXT* WINPR_RESTRICT context, BYTE type,
611 const BYTE* WINPR_RESTRICT pYUVData[3],
const UINT32 iStride[3],
612 UINT32 srcYuvHeight, BYTE* WINPR_RESTRICT pYUVDstData[3],
613 const UINT32 iDstStride[3], DWORD DstFormat, BYTE* WINPR_RESTRICT dest,
614 UINT32 nDstStep,
const RECTANGLE_16* WINPR_RESTRICT regionRects,
615 UINT32 numRegionRects)
617 const BYTE* pYUVCDstData[3];
619 WINPR_ASSERT(context);
620 WINPR_ASSERT(pYUVData);
621 WINPR_ASSERT(iStride);
622 WINPR_ASSERT(pYUVDstData);
623 WINPR_ASSERT(iDstStride);
625 WINPR_ASSERT(regionRects || (numRegionRects == 0));
627 if (context->encoder)
629 WLog_ERR(TAG,
"YUV context set up for encoding, can not decode with it, aborting");
632 if (!pool_decode_rect(context, type, pYUVData, iStride, pYUVDstData, iDstStride, regionRects,
636 pYUVCDstData[0] = pYUVDstData[0];
637 pYUVCDstData[1] = pYUVDstData[1];
638 pYUVCDstData[2] = pYUVDstData[2];
639 return pool_decode(context, yuv444_process_work_callback, pYUVCDstData, iDstStride,
640 srcYuvHeight, DstFormat, dest, nDstStep, regionRects, numRegionRects);
643 BOOL yuv420_context_decode(YUV_CONTEXT* WINPR_RESTRICT context,
644 const BYTE* WINPR_RESTRICT pYUVData[3],
const UINT32 iStride[3],
645 UINT32 yuvHeight, DWORD DstFormat, BYTE* WINPR_RESTRICT dest,
646 UINT32 nDstStep,
const RECTANGLE_16* WINPR_RESTRICT regionRects,
647 UINT32 numRegionRects)
649 return pool_decode(context, yuv420_process_work_callback, pYUVData, iStride, yuvHeight,
650 DstFormat, dest, nDstStep, regionRects, numRegionRects);
653 static void CALLBACK yuv420_encode_work_callback(PTP_CALLBACK_INSTANCE instance,
void* context,
657 YUV_ENCODE_WORK_PARAM* param = (YUV_ENCODE_WORK_PARAM*)context;
660 const BYTE* src = NULL;
662 WINPR_UNUSED(instance);
666 roi.width = param->rect.right - param->rect.left;
667 roi.height = param->rect.bottom - param->rect.top;
668 src = param->pSrcData + 1ULL * param->nSrcStep * param->rect.top +
669 1ULL * param->rect.left * FreeRDPGetBytesPerPixel(param->SrcFormat);
671 param->pYUVLumaData[0] + 1ULL * param->rect.top * param->iStride[0] + param->rect.left;
672 pYUVData[1] = param->pYUVLumaData[1] + 1ULL * param->rect.top / 2 * param->iStride[1] +
673 param->rect.left / 2;
674 pYUVData[2] = param->pYUVLumaData[2] + 1ULL * param->rect.top / 2 * param->iStride[2] +
675 param->rect.left / 2;
677 if (prims->RGBToYUV420_8u_P3AC4R(src, param->SrcFormat, param->nSrcStep, pYUVData,
678 param->iStride, &roi) != PRIMITIVES_SUCCESS)
680 WLog_ERR(TAG,
"error when decoding lines");
684 static void CALLBACK yuv444v1_encode_work_callback(PTP_CALLBACK_INSTANCE instance,
void* context,
688 YUV_ENCODE_WORK_PARAM* param = (YUV_ENCODE_WORK_PARAM*)context;
690 BYTE* pYUVLumaData[3];
691 BYTE* pYUVChromaData[3];
692 const BYTE* src = NULL;
694 WINPR_UNUSED(instance);
698 roi.width = param->rect.right - param->rect.left;
699 roi.height = param->rect.bottom - param->rect.top;
700 src = param->pSrcData + 1ULL * param->nSrcStep * param->rect.top +
701 1ULL * param->rect.left * FreeRDPGetBytesPerPixel(param->SrcFormat);
703 param->pYUVLumaData[0] + 1ULL * param->rect.top * param->iStride[0] + param->rect.left;
704 pYUVLumaData[1] = param->pYUVLumaData[1] + 1ULL * param->rect.top / 2 * param->iStride[1] +
705 param->rect.left / 2;
706 pYUVLumaData[2] = param->pYUVLumaData[2] + 1ULL * param->rect.top / 2 * param->iStride[2] +
707 param->rect.left / 2;
709 param->pYUVChromaData[0] + 1ULL * param->rect.top * param->iStride[0] + param->rect.left;
710 pYUVChromaData[1] = param->pYUVChromaData[1] + 1ULL * param->rect.top / 2 * param->iStride[1] +
711 param->rect.left / 2;
712 pYUVChromaData[2] = param->pYUVChromaData[2] + 1ULL * param->rect.top / 2 * param->iStride[2] +
713 param->rect.left / 2;
714 if (prims->RGBToAVC444YUV(src, param->SrcFormat, param->nSrcStep, pYUVLumaData, param->iStride,
715 pYUVChromaData, param->iStride, &roi) != PRIMITIVES_SUCCESS)
717 WLog_ERR(TAG,
"error when decoding lines");
721 static void CALLBACK yuv444v2_encode_work_callback(PTP_CALLBACK_INSTANCE instance,
void* context,
725 YUV_ENCODE_WORK_PARAM* param = (YUV_ENCODE_WORK_PARAM*)context;
727 BYTE* pYUVLumaData[3];
728 BYTE* pYUVChromaData[3];
729 const BYTE* src = NULL;
731 WINPR_UNUSED(instance);
735 roi.width = param->rect.right - param->rect.left;
736 roi.height = param->rect.bottom - param->rect.top;
737 src = param->pSrcData + 1ULL * param->nSrcStep * param->rect.top +
738 1ULL * param->rect.left * FreeRDPGetBytesPerPixel(param->SrcFormat);
740 param->pYUVLumaData[0] + 1ULL * param->rect.top * param->iStride[0] + param->rect.left;
741 pYUVLumaData[1] = param->pYUVLumaData[1] + 1ULL * param->rect.top / 2 * param->iStride[1] +
742 param->rect.left / 2;
743 pYUVLumaData[2] = param->pYUVLumaData[2] + 1ULL * param->rect.top / 2 * param->iStride[2] +
744 param->rect.left / 2;
746 param->pYUVChromaData[0] + 1ULL * param->rect.top * param->iStride[0] + param->rect.left;
747 pYUVChromaData[1] = param->pYUVChromaData[1] + 1ULL * param->rect.top / 2 * param->iStride[1] +
748 param->rect.left / 2;
749 pYUVChromaData[2] = param->pYUVChromaData[2] + 1ULL * param->rect.top / 2 * param->iStride[2] +
750 param->rect.left / 2;
751 if (prims->RGBToAVC444YUVv2(src, param->SrcFormat, param->nSrcStep, pYUVLumaData,
752 param->iStride, pYUVChromaData, param->iStride,
753 &roi) != PRIMITIVES_SUCCESS)
755 WLog_ERR(TAG,
"error when decoding lines");
759 static INLINE YUV_ENCODE_WORK_PARAM pool_encode_fill(
760 const RECTANGLE_16* WINPR_RESTRICT rect, YUV_CONTEXT* WINPR_RESTRICT context,
761 const BYTE* WINPR_RESTRICT pSrcData, UINT32 nSrcStep, UINT32 SrcFormat,
const UINT32 iStride[],
762 BYTE* WINPR_RESTRICT pYUVLumaData[], BYTE* WINPR_RESTRICT pYUVChromaData[])
764 YUV_ENCODE_WORK_PARAM current = { 0 };
767 WINPR_ASSERT(context);
768 WINPR_ASSERT(pSrcData);
769 WINPR_ASSERT(iStride);
770 WINPR_ASSERT(pYUVLumaData);
772 current.context = context;
773 current.pSrcData = pSrcData;
774 current.SrcFormat = SrcFormat;
775 current.nSrcStep = nSrcStep;
776 current.pYUVLumaData[0] = pYUVLumaData[0];
777 current.pYUVLumaData[1] = pYUVLumaData[1];
778 current.pYUVLumaData[2] = pYUVLumaData[2];
781 current.pYUVChromaData[0] = pYUVChromaData[0];
782 current.pYUVChromaData[1] = pYUVChromaData[1];
783 current.pYUVChromaData[2] = pYUVChromaData[2];
785 current.iStride[0] = iStride[0];
786 current.iStride[1] = iStride[1];
787 current.iStride[2] = iStride[2];
789 current.rect = *rect;
794 static BOOL pool_encode(YUV_CONTEXT* WINPR_RESTRICT context, PTP_WORK_CALLBACK cb,
795 const BYTE* WINPR_RESTRICT pSrcData, UINT32 nSrcStep, UINT32 SrcFormat,
796 const UINT32 iStride[], BYTE* WINPR_RESTRICT pYUVLumaData[],
797 BYTE* WINPR_RESTRICT pYUVChromaData[],
798 const RECTANGLE_16* WINPR_RESTRICT regionRects, UINT32 numRegionRects)
802 UINT32 waitCount = 0;
804 WINPR_ASSERT(context);
806 WINPR_ASSERT(pSrcData);
807 WINPR_ASSERT(iStride);
808 WINPR_ASSERT(regionRects || (numRegionRects == 0));
810 if (!context->encoder)
813 WLog_ERR(TAG,
"YUV context set up for decoding, can not encode with it, aborting");
817 if (!context->useThreads || (primitives_flags(prims) & PRIM_FLAGS_HAVE_EXTGPU))
819 for (UINT32 x = 0; x < numRegionRects; x++)
821 YUV_ENCODE_WORK_PARAM current =
822 pool_encode_fill(®ionRects[x], context, pSrcData, nSrcStep, SrcFormat, iStride,
823 pYUVLumaData, pYUVChromaData);
824 cb(NULL, ¤t, NULL);
830 for (UINT32 x = 0; x < numRegionRects; x++)
833 const UINT32 height = rect->bottom - rect->top;
834 const UINT32 steps = (height + context->heightStep / 2) / context->heightStep;
839 for (UINT32 x = 0; x < numRegionRects; x++)
842 const UINT32 height = rect->bottom - rect->top;
843 const UINT32 steps = (height + context->heightStep / 2) / context->heightStep;
845 for (UINT32 y = 0; y < steps; y++)
848 YUV_ENCODE_WORK_PARAM* current = NULL;
850 if (context->work_object_count <= waitCount)
853 "YUV encoder: invalid number of tiles, only support less than %" PRIu32
855 context->work_object_count, waitCount);
859 current = &context->work_enc_params[waitCount];
860 r.top += y * context->heightStep;
861 *current = pool_encode_fill(&r, context, pSrcData, nSrcStep, SrcFormat, iStride,
862 pYUVLumaData, pYUVChromaData);
863 if (!submit_object(&context->work_objects[waitCount], cb, current, context))
871 free_objects(context->work_objects, context->work_object_count);
875 BOOL yuv420_context_encode(YUV_CONTEXT* WINPR_RESTRICT context,
const BYTE* WINPR_RESTRICT pSrcData,
876 UINT32 nSrcStep, UINT32 SrcFormat,
const UINT32 iStride[3],
877 BYTE* WINPR_RESTRICT pYUVData[3],
878 const RECTANGLE_16* WINPR_RESTRICT regionRects, UINT32 numRegionRects)
880 if (!context || !pSrcData || !iStride || !pYUVData || !regionRects)
883 return pool_encode(context, yuv420_encode_work_callback, pSrcData, nSrcStep, SrcFormat, iStride,
884 pYUVData, NULL, regionRects, numRegionRects);
887 BOOL yuv444_context_encode(YUV_CONTEXT* WINPR_RESTRICT context, BYTE version,
888 const BYTE* WINPR_RESTRICT pSrcData, UINT32 nSrcStep, UINT32 SrcFormat,
889 const UINT32 iStride[3], BYTE* WINPR_RESTRICT pYUVLumaData[3],
890 BYTE* WINPR_RESTRICT pYUVChromaData[3],
891 const RECTANGLE_16* WINPR_RESTRICT regionRects, UINT32 numRegionRects)
893 PTP_WORK_CALLBACK cb = NULL;
897 cb = yuv444v1_encode_work_callback;
900 cb = yuv444v2_encode_work_callback;
906 return pool_encode(context, cb, pSrcData, nSrcStep, SrcFormat, iStride, pYUVLumaData,
907 pYUVChromaData, regionRects, numRegionRects);