1 #include <winpr/sysinfo.h>
2 #include <winpr/assert.h>
3 #include <winpr/pool.h>
5 #include <freerdp/settings.h>
6 #include <freerdp/codec/region.h>
7 #include <freerdp/primitives.h>
8 #include <freerdp/log.h>
9 #include <freerdp/codec/yuv.h>
11 #define TAG FREERDP_TAG("codec")
18 const BYTE* pYUVData[3];
24 } YUV_PROCESS_WORK_PARAM;
29 const BYTE* pYUVData[3];
35 } YUV_COMBINE_WORK_PARAM;
47 BYTE* pYUVLumaData[3];
48 BYTE* pYUVChromaData[3];
50 } YUV_ENCODE_WORK_PARAM;
63 UINT32 work_object_count;
64 PTP_WORK* work_objects;
65 YUV_ENCODE_WORK_PARAM* work_enc_params;
66 YUV_PROCESS_WORK_PARAM* work_dec_params;
67 YUV_COMBINE_WORK_PARAM* work_combined_params;
70 static INLINE BOOL avc420_yuv_to_rgb(
const BYTE* WINPR_RESTRICT pYUVData[3],
71 const UINT32 iStride[3],
72 const RECTANGLE_16* WINPR_RESTRICT rect, UINT32 nDstStep,
73 BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat)
77 const BYTE* pYUVPoint[3];
79 WINPR_ASSERT(pYUVData);
80 WINPR_ASSERT(iStride);
82 WINPR_ASSERT(pDstData);
84 const INT32 width = rect->right - rect->left;
85 const INT32 height = rect->bottom - rect->top;
86 BYTE* pDstPoint = pDstData + 1ULL * rect->top * nDstStep +
87 1ULL * rect->left * FreeRDPGetBytesPerPixel(DstFormat);
89 pYUVPoint[0] = pYUVData[0] + 1ULL * rect->top * iStride[0] + rect->left;
90 pYUVPoint[1] = pYUVData[1] + 1ULL * rect->top / 2 * iStride[1] + rect->left / 2;
91 pYUVPoint[2] = pYUVData[2] + 1ULL * rect->top / 2 * iStride[2] + rect->left / 2;
96 if (prims->YUV420ToRGB_8u_P3AC4R(pYUVPoint, iStride, pDstPoint, nDstStep, DstFormat, &roi) !=
103 static INLINE BOOL avc444_yuv_to_rgb(
const BYTE* WINPR_RESTRICT pYUVData[3],
104 const UINT32 iStride[3],
105 const RECTANGLE_16* WINPR_RESTRICT rect, UINT32 nDstStep,
106 BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat)
110 const BYTE* pYUVPoint[3];
112 WINPR_ASSERT(pYUVData);
113 WINPR_ASSERT(iStride);
115 WINPR_ASSERT(pDstData);
117 const INT32 width = rect->right - rect->left;
118 const INT32 height = rect->bottom - rect->top;
119 BYTE* pDstPoint = pDstData + 1ULL * rect->top * nDstStep +
120 1ULL * rect->left * FreeRDPGetBytesPerPixel(DstFormat);
122 pYUVPoint[0] = pYUVData[0] + 1ULL * rect->top * iStride[0] + rect->left;
123 pYUVPoint[1] = pYUVData[1] + 1ULL * rect->top * iStride[1] + rect->left;
124 pYUVPoint[2] = pYUVData[2] + 1ULL * rect->top * iStride[2] + rect->left;
129 if (prims->YUV444ToRGB_8u_P3AC4R(pYUVPoint, iStride, pDstPoint, nDstStep, DstFormat, &roi) !=
136 static void CALLBACK yuv420_process_work_callback(PTP_CALLBACK_INSTANCE instance,
void* context,
139 YUV_PROCESS_WORK_PARAM* param = (YUV_PROCESS_WORK_PARAM*)context;
140 WINPR_UNUSED(instance);
144 if (!avc420_yuv_to_rgb(param->pYUVData, param->iStride, ¶m->rect, param->nDstStep,
145 param->dest, param->DstFormat))
146 WLog_WARN(TAG,
"avc420_yuv_to_rgb failed");
149 static void CALLBACK yuv444_process_work_callback(PTP_CALLBACK_INSTANCE instance,
void* context,
152 YUV_PROCESS_WORK_PARAM* param = (YUV_PROCESS_WORK_PARAM*)context;
153 WINPR_UNUSED(instance);
157 if (!avc444_yuv_to_rgb(param->pYUVData, param->iStride, ¶m->rect, param->nDstStep,
158 param->dest, param->DstFormat))
159 WLog_WARN(TAG,
"avc444_yuv_to_rgb failed");
162 BOOL yuv_context_reset(YUV_CONTEXT* WINPR_RESTRICT context, UINT32 width, UINT32 height)
165 WINPR_ASSERT(context);
167 context->width = width;
168 context->height = height;
169 context->heightStep = (height / context->nthreads);
171 if (context->useThreads)
173 const UINT32 pw = (width + TILE_SIZE - width % TILE_SIZE) / TILE_SIZE;
174 const UINT32 ph = (height + TILE_SIZE - height % TILE_SIZE) / TILE_SIZE;
178 const UINT32 count = pw * ph * 16;
180 context->work_object_count = 0;
181 if (context->encoder)
183 void* tmp = winpr_aligned_recalloc(context->work_enc_params, count,
184 sizeof(YUV_ENCODE_WORK_PARAM), 32);
187 memset(tmp, 0, count *
sizeof(YUV_ENCODE_WORK_PARAM));
189 context->work_enc_params = tmp;
193 void* tmp = winpr_aligned_recalloc(context->work_dec_params, count,
194 sizeof(YUV_PROCESS_WORK_PARAM), 32);
197 memset(tmp, 0, count *
sizeof(YUV_PROCESS_WORK_PARAM));
199 context->work_dec_params = tmp;
201 void* ctmp = winpr_aligned_recalloc(context->work_combined_params, count,
202 sizeof(YUV_COMBINE_WORK_PARAM), 32);
205 memset(ctmp, 0, count *
sizeof(YUV_COMBINE_WORK_PARAM));
207 context->work_combined_params = ctmp;
210 void* wtmp = winpr_aligned_recalloc(context->work_objects, count,
sizeof(PTP_WORK), 32);
213 memset(wtmp, 0, count *
sizeof(PTP_WORK));
215 context->work_objects = wtmp;
216 context->work_object_count = count;
223 YUV_CONTEXT* yuv_context_new(BOOL encoder, UINT32 ThreadingFlags)
226 YUV_CONTEXT* ret = winpr_aligned_calloc(1,
sizeof(*ret), 32);
233 ret->encoder = encoder;
235 if (!(ThreadingFlags & THREADING_FLAGS_DISABLE_THREADS))
237 GetNativeSystemInfo(&sysInfos);
238 ret->useThreads = (sysInfos.dwNumberOfProcessors > 1);
241 ret->nthreads = sysInfos.dwNumberOfProcessors;
242 ret->threadPool = CreateThreadpool(NULL);
243 if (!ret->threadPool)
245 goto error_threadpool;
248 InitializeThreadpoolEnvironment(&ret->ThreadPoolEnv);
249 SetThreadpoolCallbackPool(&ret->ThreadPoolEnv, ret->threadPool);
256 WINPR_PRAGMA_DIAG_PUSH
257 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
258 yuv_context_free(ret);
259 WINPR_PRAGMA_DIAG_POP
263 void yuv_context_free(YUV_CONTEXT* context)
267 if (context->useThreads)
269 if (context->threadPool)
270 CloseThreadpool(context->threadPool);
271 DestroyThreadpoolEnvironment(&context->ThreadPoolEnv);
272 winpr_aligned_free(context->work_objects);
273 winpr_aligned_free(context->work_combined_params);
274 winpr_aligned_free(context->work_enc_params);
275 winpr_aligned_free(context->work_dec_params);
277 winpr_aligned_free(context);
280 static INLINE YUV_PROCESS_WORK_PARAM pool_decode_param(
const RECTANGLE_16* WINPR_RESTRICT rect,
281 YUV_CONTEXT* WINPR_RESTRICT context,
282 const BYTE* WINPR_RESTRICT pYUVData[3],
283 const UINT32 iStride[3], UINT32 DstFormat,
284 BYTE* WINPR_RESTRICT dest, UINT32 nDstStep)
286 YUV_PROCESS_WORK_PARAM current = { 0 };
289 WINPR_ASSERT(context);
290 WINPR_ASSERT(pYUVData);
291 WINPR_ASSERT(iStride);
294 current.context = context;
295 current.DstFormat = DstFormat;
296 current.pYUVData[0] = pYUVData[0];
297 current.pYUVData[1] = pYUVData[1];
298 current.pYUVData[2] = pYUVData[2];
299 current.iStride[0] = iStride[0];
300 current.iStride[1] = iStride[1];
301 current.iStride[2] = iStride[2];
302 current.nDstStep = nDstStep;
304 current.rect = *rect;
308 static BOOL submit_object(PTP_WORK* WINPR_RESTRICT work_object, PTP_WORK_CALLBACK cb,
309 const void* WINPR_RESTRICT param, YUV_CONTEXT* WINPR_RESTRICT context)
324 if (!param || !context)
327 *work_object = CreateThreadpoolWork(cb, cnv.pv, &context->ThreadPoolEnv);
331 SubmitThreadpoolWork(*work_object);
335 static void free_objects(PTP_WORK* work_objects, UINT32 waitCount)
337 WINPR_ASSERT(work_objects || (waitCount == 0));
339 for (UINT32 i = 0; i < waitCount; i++)
341 PTP_WORK cur = work_objects[i];
342 work_objects[i] = NULL;
347 WaitForThreadpoolWorkCallbacks(cur, FALSE);
348 CloseThreadpoolWork(cur);
352 static BOOL intersects(UINT32 pos,
const RECTANGLE_16* WINPR_RESTRICT regionRects,
353 UINT32 numRegionRects)
355 WINPR_ASSERT(regionRects || (numRegionRects == 0));
357 for (UINT32 x = pos + 1; x < numRegionRects; x++)
362 if (rectangles_intersects(what, rect))
364 WLog_WARN(TAG,
"YUV decoder: intersecting rectangles, aborting");
372 static RECTANGLE_16 clamp(YUV_CONTEXT* WINPR_RESTRICT context,
373 const RECTANGLE_16* WINPR_RESTRICT rect, UINT32 srcHeight)
375 WINPR_ASSERT(context);
379 const UINT32 height = MIN(context->height, srcHeight);
382 if (c.bottom > height)
387 static BOOL pool_decode(YUV_CONTEXT* WINPR_RESTRICT context, PTP_WORK_CALLBACK cb,
388 const BYTE* WINPR_RESTRICT pYUVData[3],
const UINT32 iStride[3],
389 UINT32 yuvHeight, UINT32 DstFormat, BYTE* WINPR_RESTRICT dest,
390 UINT32 nDstStep,
const RECTANGLE_16* WINPR_RESTRICT regionRects,
391 UINT32 numRegionRects)
394 UINT32 waitCount = 0;
397 WINPR_ASSERT(context);
399 WINPR_ASSERT(pYUVData);
400 WINPR_ASSERT(iStride);
402 WINPR_ASSERT(regionRects || (numRegionRects == 0));
404 if (context->encoder)
406 WLog_ERR(TAG,
"YUV context set up for encoding, can not decode with it, aborting");
410 if (!context->useThreads || (primitives_flags(prims) & PRIM_FLAGS_HAVE_EXTGPU))
412 for (UINT32 y = 0; y < numRegionRects; y++)
414 const RECTANGLE_16 rect = clamp(context, ®ionRects[y], yuvHeight);
415 YUV_PROCESS_WORK_PARAM current =
416 pool_decode_param(&rect, context, pYUVData, iStride, DstFormat, dest, nDstStep);
417 cb(NULL, ¤t, NULL);
423 for (UINT32 x = 0; x < numRegionRects; x++)
425 RECTANGLE_16 r = clamp(context, ®ionRects[x], yuvHeight);
427 if (intersects(x, regionRects, numRegionRects))
430 while (r.left < r.right)
433 y.right = MIN(r.right, r.left + TILE_SIZE);
435 while (y.top < y.bottom)
439 if (context->work_object_count <= waitCount)
442 "YUV decoder: invalid number of tiles, only support less than %" PRIu32
444 context->work_object_count, waitCount);
448 YUV_PROCESS_WORK_PARAM* cur = &context->work_dec_params[waitCount];
449 z.bottom = MIN(z.bottom, z.top + TILE_SIZE);
450 if (rectangle_is_empty(&z))
452 *cur = pool_decode_param(&z, context, pYUVData, iStride, DstFormat, dest, nDstStep);
453 if (!submit_object(&context->work_objects[waitCount], cb, cur, context))
464 free_objects(context->work_objects, context->work_object_count);
468 static INLINE BOOL check_rect(
const YUV_CONTEXT* WINPR_RESTRICT yuv,
469 const RECTANGLE_16* WINPR_RESTRICT rect, UINT32 nDstWidth,
476 if ((rect->right > yuv->width) || (rect->left > yuv->width))
479 if ((rect->top > yuv->height) || (rect->bottom > yuv->height))
483 if ((rect->right > nDstWidth) || (rect->left > nDstWidth))
486 if ((rect->bottom > nDstHeight) || (rect->top > nDstHeight))
492 static void CALLBACK yuv444_combine_work_callback(PTP_CALLBACK_INSTANCE instance,
void* context,
495 YUV_COMBINE_WORK_PARAM* param = (YUV_COMBINE_WORK_PARAM*)context;
499 YUV_CONTEXT* yuv = param->context;
505 const UINT32 alignedWidth = yuv->width + ((yuv->width % 16 != 0) ? 16 - yuv->width % 16 : 0);
506 const UINT32 alignedHeight =
507 yuv->height + ((yuv->height % 16 != 0) ? 16 - yuv->height % 16 : 0);
509 WINPR_UNUSED(instance);
512 if (!check_rect(param->context, rect, yuv->width, yuv->height))
515 if (prims->YUV420CombineToYUV444(param->type, param->pYUVData, param->iStride, alignedWidth,
516 alignedHeight, param->pYUVDstData, param->iDstStride,
517 rect) != PRIMITIVES_SUCCESS)
518 WLog_WARN(TAG,
"YUV420CombineToYUV444 failed");
521 static INLINE YUV_COMBINE_WORK_PARAM
522 pool_decode_rect_param(
const RECTANGLE_16* WINPR_RESTRICT rect, YUV_CONTEXT* WINPR_RESTRICT context,
523 BYTE type,
const BYTE* WINPR_RESTRICT pYUVData[3],
const UINT32 iStride[3],
524 BYTE* WINPR_RESTRICT pYUVDstData[3],
const UINT32 iDstStride[3])
526 YUV_COMBINE_WORK_PARAM current = { 0 };
529 WINPR_ASSERT(context);
530 WINPR_ASSERT(pYUVData);
531 WINPR_ASSERT(iStride);
532 WINPR_ASSERT(pYUVDstData);
533 WINPR_ASSERT(iDstStride);
535 current.context = context;
536 current.pYUVData[0] = pYUVData[0];
537 current.pYUVData[1] = pYUVData[1];
538 current.pYUVData[2] = pYUVData[2];
539 current.pYUVDstData[0] = pYUVDstData[0];
540 current.pYUVDstData[1] = pYUVDstData[1];
541 current.pYUVDstData[2] = pYUVDstData[2];
542 current.iStride[0] = iStride[0];
543 current.iStride[1] = iStride[1];
544 current.iStride[2] = iStride[2];
545 current.iDstStride[0] = iDstStride[0];
546 current.iDstStride[1] = iDstStride[1];
547 current.iDstStride[2] = iDstStride[2];
549 current.rect = *rect;
553 static BOOL pool_decode_rect(YUV_CONTEXT* WINPR_RESTRICT context, BYTE type,
554 const BYTE* WINPR_RESTRICT pYUVData[3],
const UINT32 iStride[3],
555 BYTE* WINPR_RESTRICT pYUVDstData[3],
const UINT32 iDstStride[3],
556 const RECTANGLE_16* WINPR_RESTRICT regionRects, UINT32 numRegionRects)
559 UINT32 waitCount = 0;
560 PTP_WORK_CALLBACK cb = yuv444_combine_work_callback;
563 WINPR_ASSERT(context);
564 WINPR_ASSERT(pYUVData);
565 WINPR_ASSERT(iStride);
566 WINPR_ASSERT(pYUVDstData);
567 WINPR_ASSERT(iDstStride);
568 WINPR_ASSERT(regionRects || (numRegionRects == 0));
570 if (!context->useThreads || (primitives_flags(prims) & PRIM_FLAGS_HAVE_EXTGPU))
572 for (UINT32 y = 0; y < numRegionRects; y++)
574 YUV_COMBINE_WORK_PARAM current = pool_decode_rect_param(
575 ®ionRects[y], context, type, pYUVData, iStride, pYUVDstData, iDstStride);
576 cb(NULL, ¤t, NULL);
582 for (waitCount = 0; waitCount < numRegionRects; waitCount++)
584 YUV_COMBINE_WORK_PARAM* current = NULL;
586 if (context->work_object_count <= waitCount)
589 "YUV rect decoder: invalid number of tiles, only support less than %" PRIu32
591 context->work_object_count, waitCount);
594 current = &context->work_combined_params[waitCount];
595 *current = pool_decode_rect_param(®ionRects[waitCount], context, type, pYUVData, iStride,
596 pYUVDstData, iDstStride);
598 if (!submit_object(&context->work_objects[waitCount], cb, current, context))
604 free_objects(context->work_objects, context->work_object_count);
608 BOOL yuv444_context_decode(YUV_CONTEXT* WINPR_RESTRICT context, BYTE type,
609 const BYTE* WINPR_RESTRICT pYUVData[3],
const UINT32 iStride[3],
610 UINT32 srcYuvHeight, BYTE* WINPR_RESTRICT pYUVDstData[3],
611 const UINT32 iDstStride[3], DWORD DstFormat, BYTE* WINPR_RESTRICT dest,
612 UINT32 nDstStep,
const RECTANGLE_16* WINPR_RESTRICT regionRects,
613 UINT32 numRegionRects)
615 const BYTE* pYUVCDstData[3];
617 WINPR_ASSERT(context);
618 WINPR_ASSERT(pYUVData);
619 WINPR_ASSERT(iStride);
620 WINPR_ASSERT(pYUVDstData);
621 WINPR_ASSERT(iDstStride);
623 WINPR_ASSERT(regionRects || (numRegionRects == 0));
625 if (context->encoder)
627 WLog_ERR(TAG,
"YUV context set up for encoding, can not decode with it, aborting");
630 if (!pool_decode_rect(context, type, pYUVData, iStride, pYUVDstData, iDstStride, regionRects,
634 pYUVCDstData[0] = pYUVDstData[0];
635 pYUVCDstData[1] = pYUVDstData[1];
636 pYUVCDstData[2] = pYUVDstData[2];
637 return pool_decode(context, yuv444_process_work_callback, pYUVCDstData, iDstStride,
638 srcYuvHeight, DstFormat, dest, nDstStep, regionRects, numRegionRects);
641 BOOL yuv420_context_decode(YUV_CONTEXT* WINPR_RESTRICT context,
642 const BYTE* WINPR_RESTRICT pYUVData[3],
const UINT32 iStride[3],
643 UINT32 yuvHeight, DWORD DstFormat, BYTE* WINPR_RESTRICT dest,
644 UINT32 nDstStep,
const RECTANGLE_16* WINPR_RESTRICT regionRects,
645 UINT32 numRegionRects)
647 return pool_decode(context, yuv420_process_work_callback, pYUVData, iStride, yuvHeight,
648 DstFormat, dest, nDstStep, regionRects, numRegionRects);
651 static void CALLBACK yuv420_encode_work_callback(PTP_CALLBACK_INSTANCE instance,
void* context,
655 YUV_ENCODE_WORK_PARAM* param = (YUV_ENCODE_WORK_PARAM*)context;
658 const BYTE* src = NULL;
660 WINPR_UNUSED(instance);
664 roi.width = param->rect.right - param->rect.left;
665 roi.height = param->rect.bottom - param->rect.top;
666 src = param->pSrcData + 1ULL * param->nSrcStep * param->rect.top +
667 1ULL * param->rect.left * FreeRDPGetBytesPerPixel(param->SrcFormat);
669 param->pYUVLumaData[0] + 1ULL * param->rect.top * param->iStride[0] + param->rect.left;
670 pYUVData[1] = param->pYUVLumaData[1] + 1ULL * param->rect.top / 2 * param->iStride[1] +
671 param->rect.left / 2;
672 pYUVData[2] = param->pYUVLumaData[2] + 1ULL * param->rect.top / 2 * param->iStride[2] +
673 param->rect.left / 2;
675 if (prims->RGBToYUV420_8u_P3AC4R(src, param->SrcFormat, param->nSrcStep, pYUVData,
676 param->iStride, &roi) != PRIMITIVES_SUCCESS)
678 WLog_ERR(TAG,
"error when decoding lines");
682 static void CALLBACK yuv444v1_encode_work_callback(PTP_CALLBACK_INSTANCE instance,
void* context,
686 YUV_ENCODE_WORK_PARAM* param = (YUV_ENCODE_WORK_PARAM*)context;
688 BYTE* pYUVLumaData[3];
689 BYTE* pYUVChromaData[3];
690 const BYTE* src = NULL;
692 WINPR_UNUSED(instance);
696 roi.width = param->rect.right - param->rect.left;
697 roi.height = param->rect.bottom - param->rect.top;
698 src = param->pSrcData + 1ULL * param->nSrcStep * param->rect.top +
699 1ULL * param->rect.left * FreeRDPGetBytesPerPixel(param->SrcFormat);
701 param->pYUVLumaData[0] + 1ULL * param->rect.top * param->iStride[0] + param->rect.left;
702 pYUVLumaData[1] = param->pYUVLumaData[1] + 1ULL * param->rect.top / 2 * param->iStride[1] +
703 param->rect.left / 2;
704 pYUVLumaData[2] = param->pYUVLumaData[2] + 1ULL * param->rect.top / 2 * param->iStride[2] +
705 param->rect.left / 2;
707 param->pYUVChromaData[0] + 1ULL * param->rect.top * param->iStride[0] + param->rect.left;
708 pYUVChromaData[1] = param->pYUVChromaData[1] + 1ULL * param->rect.top / 2 * param->iStride[1] +
709 param->rect.left / 2;
710 pYUVChromaData[2] = param->pYUVChromaData[2] + 1ULL * param->rect.top / 2 * param->iStride[2] +
711 param->rect.left / 2;
712 if (prims->RGBToAVC444YUV(src, param->SrcFormat, param->nSrcStep, pYUVLumaData, param->iStride,
713 pYUVChromaData, param->iStride, &roi) != PRIMITIVES_SUCCESS)
715 WLog_ERR(TAG,
"error when decoding lines");
719 static void CALLBACK yuv444v2_encode_work_callback(PTP_CALLBACK_INSTANCE instance,
void* context,
723 YUV_ENCODE_WORK_PARAM* param = (YUV_ENCODE_WORK_PARAM*)context;
725 BYTE* pYUVLumaData[3];
726 BYTE* pYUVChromaData[3];
727 const BYTE* src = NULL;
729 WINPR_UNUSED(instance);
733 roi.width = param->rect.right - param->rect.left;
734 roi.height = param->rect.bottom - param->rect.top;
735 src = param->pSrcData + 1ULL * param->nSrcStep * param->rect.top +
736 1ULL * param->rect.left * FreeRDPGetBytesPerPixel(param->SrcFormat);
738 param->pYUVLumaData[0] + 1ULL * param->rect.top * param->iStride[0] + param->rect.left;
739 pYUVLumaData[1] = param->pYUVLumaData[1] + 1ULL * param->rect.top / 2 * param->iStride[1] +
740 param->rect.left / 2;
741 pYUVLumaData[2] = param->pYUVLumaData[2] + 1ULL * param->rect.top / 2 * param->iStride[2] +
742 param->rect.left / 2;
744 param->pYUVChromaData[0] + 1ULL * param->rect.top * param->iStride[0] + param->rect.left;
745 pYUVChromaData[1] = param->pYUVChromaData[1] + 1ULL * param->rect.top / 2 * param->iStride[1] +
746 param->rect.left / 2;
747 pYUVChromaData[2] = param->pYUVChromaData[2] + 1ULL * param->rect.top / 2 * param->iStride[2] +
748 param->rect.left / 2;
749 if (prims->RGBToAVC444YUVv2(src, param->SrcFormat, param->nSrcStep, pYUVLumaData,
750 param->iStride, pYUVChromaData, param->iStride,
751 &roi) != PRIMITIVES_SUCCESS)
753 WLog_ERR(TAG,
"error when decoding lines");
757 static INLINE YUV_ENCODE_WORK_PARAM pool_encode_fill(
758 const RECTANGLE_16* WINPR_RESTRICT rect, YUV_CONTEXT* WINPR_RESTRICT context,
759 const BYTE* WINPR_RESTRICT pSrcData, UINT32 nSrcStep, UINT32 SrcFormat,
const UINT32 iStride[],
760 BYTE* WINPR_RESTRICT pYUVLumaData[], BYTE* WINPR_RESTRICT pYUVChromaData[])
762 YUV_ENCODE_WORK_PARAM current = { 0 };
765 WINPR_ASSERT(context);
766 WINPR_ASSERT(pSrcData);
767 WINPR_ASSERT(iStride);
768 WINPR_ASSERT(pYUVLumaData);
770 current.context = context;
771 current.pSrcData = pSrcData;
772 current.SrcFormat = SrcFormat;
773 current.nSrcStep = nSrcStep;
774 current.pYUVLumaData[0] = pYUVLumaData[0];
775 current.pYUVLumaData[1] = pYUVLumaData[1];
776 current.pYUVLumaData[2] = pYUVLumaData[2];
779 current.pYUVChromaData[0] = pYUVChromaData[0];
780 current.pYUVChromaData[1] = pYUVChromaData[1];
781 current.pYUVChromaData[2] = pYUVChromaData[2];
783 current.iStride[0] = iStride[0];
784 current.iStride[1] = iStride[1];
785 current.iStride[2] = iStride[2];
787 current.rect = *rect;
792 static BOOL pool_encode(YUV_CONTEXT* WINPR_RESTRICT context, PTP_WORK_CALLBACK cb,
793 const BYTE* WINPR_RESTRICT pSrcData, UINT32 nSrcStep, UINT32 SrcFormat,
794 const UINT32 iStride[], BYTE* WINPR_RESTRICT pYUVLumaData[],
795 BYTE* WINPR_RESTRICT pYUVChromaData[],
796 const RECTANGLE_16* WINPR_RESTRICT regionRects, UINT32 numRegionRects)
800 UINT32 waitCount = 0;
802 WINPR_ASSERT(context);
804 WINPR_ASSERT(pSrcData);
805 WINPR_ASSERT(iStride);
806 WINPR_ASSERT(regionRects || (numRegionRects == 0));
808 if (!context->encoder)
811 WLog_ERR(TAG,
"YUV context set up for decoding, can not encode with it, aborting");
815 if (!context->useThreads || (primitives_flags(prims) & PRIM_FLAGS_HAVE_EXTGPU))
817 for (UINT32 x = 0; x < numRegionRects; x++)
819 YUV_ENCODE_WORK_PARAM current =
820 pool_encode_fill(®ionRects[x], context, pSrcData, nSrcStep, SrcFormat, iStride,
821 pYUVLumaData, pYUVChromaData);
822 cb(NULL, ¤t, NULL);
828 for (UINT32 x = 0; x < numRegionRects; x++)
831 const UINT32 height = rect->bottom - rect->top;
832 const UINT32 steps = (height + context->heightStep / 2) / context->heightStep;
837 for (UINT32 x = 0; x < numRegionRects; x++)
840 const UINT32 height = rect->bottom - rect->top;
841 const UINT32 steps = (height + context->heightStep / 2) / context->heightStep;
843 for (UINT32 y = 0; y < steps; y++)
846 YUV_ENCODE_WORK_PARAM* current = NULL;
848 if (context->work_object_count <= waitCount)
851 "YUV encoder: invalid number of tiles, only support less than %" PRIu32
853 context->work_object_count, waitCount);
857 current = &context->work_enc_params[waitCount];
858 r.top += y * context->heightStep;
859 *current = pool_encode_fill(&r, context, pSrcData, nSrcStep, SrcFormat, iStride,
860 pYUVLumaData, pYUVChromaData);
861 if (!submit_object(&context->work_objects[waitCount], cb, current, context))
869 free_objects(context->work_objects, context->work_object_count);
873 BOOL yuv420_context_encode(YUV_CONTEXT* WINPR_RESTRICT context,
const BYTE* WINPR_RESTRICT pSrcData,
874 UINT32 nSrcStep, UINT32 SrcFormat,
const UINT32 iStride[3],
875 BYTE* WINPR_RESTRICT pYUVData[3],
876 const RECTANGLE_16* WINPR_RESTRICT regionRects, UINT32 numRegionRects)
878 if (!context || !pSrcData || !iStride || !pYUVData || !regionRects)
881 return pool_encode(context, yuv420_encode_work_callback, pSrcData, nSrcStep, SrcFormat, iStride,
882 pYUVData, NULL, regionRects, numRegionRects);
885 BOOL yuv444_context_encode(YUV_CONTEXT* WINPR_RESTRICT context, BYTE version,
886 const BYTE* WINPR_RESTRICT pSrcData, UINT32 nSrcStep, UINT32 SrcFormat,
887 const UINT32 iStride[3], BYTE* WINPR_RESTRICT pYUVLumaData[3],
888 BYTE* WINPR_RESTRICT pYUVChromaData[3],
889 const RECTANGLE_16* WINPR_RESTRICT regionRects, UINT32 numRegionRects)
891 PTP_WORK_CALLBACK cb = NULL;
895 cb = yuv444v1_encode_work_callback;
898 cb = yuv444v2_encode_work_callback;
904 return pool_encode(context, cb, pSrcData, nSrcStep, SrcFormat, iStride, pYUVLumaData,
905 pYUVChromaData, regionRects, numRegionRects);