FreeRDP
Loading...
Searching...
No Matches
av1.c
1
21#include <freerdp/codec/av1.h>
22#include <freerdp/primitives.h>
23#include <freerdp/log.h>
24#include <freerdp/codec/region.h>
25
26#define TAG FREERDP_TAG("codec.av1")
27
28#if defined(WITH_LIBAOM)
29#include <aom/aom.h>
30
31#include <aom/aom_decoder.h>
32#include <aom/aom_encoder.h>
33
34#include <aom/aom_image.h>
35#include <aom/aomcx.h>
36#include <aom/aomdx.h>
37
38#if defined(WITH_LIBYUV)
39#include <libyuv.h>
40#endif
41
42struct S_FREERDP_AV1_CONTEXT
43{
44 aom_codec_ctx_t ctx;
45 wLog* log;
46 bool encoder;
47 bool initialized;
48 aom_codec_enc_cfg_t ecfg;
49 aom_codec_dec_cfg_t dcfg;
50 aom_codec_pts_t framecount;
51 aom_enc_frame_flags_t eflags;
52 aom_codec_flags_t flags;
53 aom_codec_iface_t* iface;
54 BYTE* yuvdata[3];
55 UINT32 yuvWidth;
56 UINT32 yuvStride[3];
57 UINT32 yuvHeight;
58};
59
60WINPR_ATTR_NODISCARD
61static BOOL allocate_h264_metablock(UINT32 QP, RECTANGLE_16* rectangles,
62 RDPGFX_H264_METABLOCK* meta, size_t count)
63{
64 /* [MS-RDPEGFX] 2.2.4.4.2 RDPGFX_AVC420_QUANT_QUALITY */
65 if (!meta || (QP > UINT8_MAX))
66 {
67 free(rectangles);
68 return FALSE;
69 }
70
71 meta->regionRects = rectangles;
72 if (count == 0)
73 return TRUE;
74
75 if (count > UINT32_MAX)
76 return FALSE;
77
78 meta->quantQualityVals = calloc(count, sizeof(RDPGFX_H264_QUANT_QUALITY));
79
80 if (!meta->quantQualityVals || !meta->regionRects)
81 return FALSE;
82 meta->numRegionRects = (UINT32)count;
83 for (size_t x = 0; x < count; x++)
84 {
85 RDPGFX_H264_QUANT_QUALITY* cur = &meta->quantQualityVals[x];
86 cur->qp = (UINT8)QP;
87
88 /* qpVal bit 6 and 7 are flags, so mask them out here.
89 * qualityVal is [0-100] so 100 - qpVal [0-64] is always in range */
90 cur->qualityVal = 100 - (QP & 0x3F);
91 }
92 return TRUE;
93}
94
95BOOL freerdp_av1_context_set_option(FREERDP_AV1_CONTEXT* av1, FREERDP_AV1_CONTEXT_OPTION option,
96 UINT32 value)
97{
98
99 switch (option)
100 {
101 case FREERDP_AV1_CONTEXT_OPTION_PROFILE:
102 if (!av1->encoder)
103 return FALSE;
104
105 av1->ecfg.g_profile = value;
106 break;
107
108 case FREERDP_AV1_CONTEXT_OPTION_RATECONTROL:
109 if (!av1->encoder)
110 return FALSE;
111 switch (value)
112 {
113 case FREERDP_AV1_VBR:
114 case FREERDP_AV1_CBR:
115 case FREERDP_AV1_CQ:
116 case FREERDP_AV1_Q:
117 break;
118 default:
119 WLog_Print(av1->log, WLOG_WARN,
120 "Unknown FREERDP_AV1_CONTEXT_OPTION_RATECONTROL value [0x%08" PRIx32
121 "]",
122 value);
123 return FALSE;
124 }
125 av1->ecfg.rc_end_usage = value;
126 break;
127 case FREERDP_AV1_CONTEXT_OPTION_BITRATE:
128 if (!av1->encoder)
129 return FALSE;
130 av1->ecfg.rc_target_bitrate = value;
131 break;
132 case FREERDP_AV1_CONTEXT_OPTION_USAGETYPE:
133 if (!av1->encoder)
134 return FALSE;
135 av1->ecfg.g_usage = value;
136 break;
137 default:
138 WLog_Print(av1->log, WLOG_ERROR, "Unknown FREERDP_AV1_CONTEXT_OPTION[0x%08" PRIx32 "]",
139 option);
140 return TRUE;
141 }
142 return freerdp_av1_context_reset(av1, av1->ecfg.g_w, av1->ecfg.g_h);
143}
144
145UINT32 freerdp_av1_context_get_option(FREERDP_AV1_CONTEXT* av1, FREERDP_AV1_CONTEXT_OPTION option)
146{
147 switch (option)
148 {
149 case FREERDP_AV1_CONTEXT_OPTION_PROFILE:
150 if (!av1->encoder)
151 return 0;
152 return av1->ecfg.g_profile;
153 case FREERDP_AV1_CONTEXT_OPTION_RATECONTROL:
154 if (!av1->encoder)
155 return 0;
156 return av1->ecfg.rc_end_usage;
157 case FREERDP_AV1_CONTEXT_OPTION_BITRATE:
158 if (!av1->encoder)
159 return 0;
160 return av1->ecfg.rc_target_bitrate;
161 case FREERDP_AV1_CONTEXT_OPTION_USAGETYPE:
162 if (!av1->encoder)
163 return 0;
164 return av1->ecfg.g_usage;
165 default:
166 WLog_Print(av1->log, WLOG_ERROR, "Unknown FREERDP_AV1_CONTEXT_OPTION[0x%08" PRIx32 "]",
167 option);
168 return 0;
169 }
170}
171
172INT32 freerdp_av1_compress(FREERDP_AV1_CONTEXT* av1, const BYTE* pSrcData, DWORD SrcFormat,
173 UINT32 nSrcStep, UINT32 nSrcWidth, UINT32 nSrcHeight,
174 const RECTANGLE_16* regionRect, BYTE** ppDstData, UINT32* pDstSize,
176{
177 *ppDstData = nullptr;
178 *pDstSize = 0;
179
180 if (!av1->encoder)
181 {
182 WLog_Print(av1->log, WLOG_ERROR, "av1->encoder: %d", av1->encoder);
183 return -1;
184 }
185
186 primitives_t* primitives = primitives_get();
187 if (!primitives)
188 {
189 WLog_Print(av1->log, WLOG_ERROR, "primitives_get(): nullptr");
190 return -1;
191 }
192
193 if (av1->yuvWidth != nSrcWidth)
194 {
195 WLog_Print(av1->log, WLOG_ERROR, "av1->yuvWidth[%" PRIu32 "] != nSrcWidth[%" PRIu32 "]",
196 av1->yuvWidth, nSrcWidth);
197 return -1;
198 }
199
200 if (av1->yuvHeight != nSrcHeight)
201 {
202 WLog_Print(av1->log, WLOG_ERROR, "av1->yuvHeight[%" PRIu32 "] != nSrcHeight[%" PRIu32 "]",
203 av1->yuvHeight, nSrcHeight);
204 return -1;
205 }
206
207 const prim_size_t roi = { .width = nSrcWidth, .height = nSrcHeight };
208
209 aom_image_t buffer = WINPR_C_ARRAY_INIT;
210
211 aom_image_t* img = &buffer;
212#if defined(WITH_LIBYUV)
213 int rec = -1;
214 switch (av1->ecfg.g_profile)
215 {
216 case 0:
217 img->fmt = AOM_IMG_FMT_I420;
218 img->x_chroma_shift = 1;
219 img->y_chroma_shift = 1;
220 rec = ARGBToI420(pSrcData, nSrcStep, av1->yuvdata[0], av1->yuvStride[0],
221 av1->yuvdata[1], av1->yuvStride[1], av1->yuvdata[2],
222 WINPR_ASSERTING_INT_CAST(int, av1->yuvStride[2]),
223 WINPR_ASSERTING_INT_CAST(int, roi.width),
224 WINPR_ASSERTING_INT_CAST(int, roi.height));
225 break;
226 case 1:
227 img->fmt = AOM_IMG_FMT_I444;
228 rec = ARGBToI444(pSrcData, nSrcStep, av1->yuvdata[0], av1->yuvStride[0],
229 av1->yuvdata[1], av1->yuvStride[1], av1->yuvdata[2],
230 WINPR_ASSERTING_INT_CAST(int, av1->yuvStride[2]),
231 WINPR_ASSERTING_INT_CAST(int, roi.width),
232 WINPR_ASSERTING_INT_CAST(int, roi.height));
233 break;
234 default:
235 WLog_Print(av1->log, WLOG_ERROR, "Unsupoorted AV1 profile %" PRIu32,
236 av1->ecfg.g_profile);
237 return -1;
238 }
239 if (rec != 0)
240 {
241 WLog_Print(av1->log, WLOG_ERROR, "ARGBToI444(): %d", rec);
242 return -1;
243 }
244#else
245 pstatus_t rec = -1;
246 switch (av1->ecfg.g_profile)
247 {
248 case 0:
249 img->fmt = AOM_IMG_FMT_I420;
250 img->x_chroma_shift = 1;
251 img->y_chroma_shift = 1;
252 rec = primitives->RGBToYUV420_8u_P3AC4R(pSrcData, SrcFormat, nSrcStep, av1->yuvdata,
253 av1->yuvStride, &roi);
254 break;
255 case 1:
256 img->fmt = AOM_IMG_FMT_I444;
257 rec = primitives->RGBToI444_8u(pSrcData, SrcFormat, nSrcStep, av1->yuvdata,
258 av1->yuvStride, &roi);
259 break;
260 default:
261 WLog_Print(av1->log, WLOG_ERROR, "Unsupoorted AV1 profile %" PRIu32,
262 av1->ecfg.g_profile);
263 return -1;
264 }
265 if (rec != 0)
266 {
267 WLog_Print(av1->log, WLOG_ERROR, "primitives->RGBToI444_8u(): %d", rec);
268 return -1;
269 }
270#endif
271 img->bit_depth = 8;
272 img->d_w = img->r_w = img->w = roi.width;
273 img->d_h = img->r_h = img->h = roi.height;
274 img->stride[0] = WINPR_ASSERTING_INT_CAST(int, av1->yuvStride[0]);
275 img->stride[1] = WINPR_ASSERTING_INT_CAST(int, av1->yuvStride[1]);
276 img->stride[2] = WINPR_ASSERTING_INT_CAST(int, av1->yuvStride[2]);
277 img->planes[0] = av1->yuvdata[0];
278 img->planes[1] = av1->yuvdata[1];
279 img->planes[2] = av1->yuvdata[2];
280
281 const aom_codec_err_t rc = aom_codec_encode(&av1->ctx, img, ++av1->framecount, 1, av1->eflags);
282 aom_img_free(img);
283
284 if (rc != AOM_CODEC_OK)
285 {
286 WLog_Print(av1->log, WLOG_WARN, "aom_codec_encode: %s", aom_codec_err_to_string(rc));
287 return -1;
288 }
289
290 aom_codec_iter_t iter = nullptr;
291 const aom_codec_cx_pkt_t* pkt = nullptr;
292 while ((pkt = aom_codec_get_cx_data(&av1->ctx, &iter)) != nullptr)
293 {
294 if (pkt->kind != AOM_CODEC_CX_FRAME_PKT)
295 continue;
296
297 *ppDstData = pkt->data.frame.buf;
298 *pDstSize = pkt->data.frame.sz;
299 };
300 if (*pDstSize == 0)
301 return 0;
302
303 RECTANGLE_16* rect = calloc(1, sizeof(RECTANGLE_16));
304 if (rect)
305 {
306 rect->right = nSrcWidth;
307 rect->bottom = nSrcHeight;
308 }
309 return allocate_h264_metablock(10, rect, meta, 1);
310}
311
312static BOOL isRectValid(UINT32 width, UINT32 height, const RECTANGLE_16* rect)
313{
314 WINPR_ASSERT(rect);
315 if (rect->left > width)
316 return FALSE;
317 if (rect->right > width)
318 return FALSE;
319 if (rect->left >= rect->right)
320 return FALSE;
321 if (rect->top > height)
322 return FALSE;
323 if (rect->bottom > height)
324 return FALSE;
325 if (rect->top >= rect->bottom)
326 return FALSE;
327 return TRUE;
328}
329
330static BOOL areRectsValid(wLog* log, UINT32 width, UINT32 height, const RECTANGLE_16* rects,
331 UINT32 count)
332{
333 WINPR_ASSERT(rects || (count == 0));
334 for (size_t x = 0; x < count; x++)
335 {
336 const RECTANGLE_16* rect = &rects[x];
337 if (!isRectValid(width, height, rect))
338 {
339 char buffer[64] = WINPR_C_ARRAY_INIT;
340 WLog_Print(log, WLOG_WARN,
341 "Rectangle %" PRIuz " %s outside of bounding frame %" PRIu32 "x%" PRIu32, x,
342 rectangle_to_string(rect, buffer, sizeof(buffer)), width, height);
343 return FALSE;
344 }
345 }
346 return TRUE;
347}
348
349INT32 freerdp_av1_decompress(FREERDP_AV1_CONTEXT* av1, const BYTE* pSrcData, UINT32 SrcSize,
350 BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nDstWidth,
351 UINT32 nDstHeight, const RECTANGLE_16* regionRects,
352 UINT32 numRegionRect)
353{
354 WINPR_ASSERT(av1);
355 if (av1->encoder)
356 {
357 WLog_Print(av1->log, WLOG_ERROR, "av1->encoder: %d", av1->encoder);
358 return -1;
359 }
360
361 if (!areRectsValid(av1->log, nDstWidth, nDstHeight, regionRects, numRegionRect))
362 return -2;
363
364 const aom_codec_err_t rc = aom_codec_decode(&av1->ctx, pSrcData, SrcSize, nullptr);
365 if (rc != AOM_CODEC_OK)
366 {
367 WLog_Print(av1->log, WLOG_WARN, "aom_codec_decode: %s", aom_codec_err_to_string(rc));
368 return -1;
369 }
370
371 aom_image_t* img = nullptr;
372 aom_codec_iter_t iter = nullptr;
373 while ((img = aom_codec_get_frame(&av1->ctx, &iter)) != nullptr)
374 {
375 /* The decoded frame may be smaller than the destination surface, so
376 * bound the converted region to it. Otherwise the colour conversion
377 * reads past the decoded image planes. */
378 const UINT32 nWidth = (img->d_w < nDstWidth) ? img->d_w : nDstWidth;
379 const UINT32 nHeight = (img->d_h < nDstHeight) ? img->d_h : nDstHeight;
380 const prim_size_t roi = { .width = nWidth, .height = nHeight };
381
382 if (!areRectsValid(av1->log, roi.width, roi.height, regionRects, numRegionRect))
383 return -2;
384
385#if defined(WITH_LIBYUV)
386 int rec = -1;
387
388 switch (img->fmt)
389 {
390 case AOM_IMG_FMT_I420:
391 rec =
392 J420ToARGB(img->planes[0], img->stride[0], img->planes[1], img->stride[1],
393 img->planes[2], img->stride[2], pDstData, nDstStep, nWidth, nHeight);
394 break;
395 case AOM_IMG_FMT_I444:
396 rec =
397 J444ToARGB(img->planes[0], img->stride[0], img->planes[1], img->stride[1],
398 img->planes[2], img->stride[2], pDstData, nDstStep, nWidth, nHeight);
399 break;
400 default:
401 WLog_Print(av1->log, WLOG_ERROR, "img->fmt %d not supported", img->fmt);
402 return -1;
403 }
404 if (rec != 0)
405 {
406 WLog_Print(av1->log, WLOG_ERROR, "I444ToABGR() %d", rec);
407 return -1;
408 }
409#else
410 const BYTE* pSrc[] = { img->planes[0], img->planes[1], img->planes[2] };
411 const UINT32 strides[] = { img->stride[0], img->stride[1], img->stride[2] };
412
413 primitives_t* primitives = primitives_get();
414 if (!primitives)
415 {
416 WLog_Print(av1->log, WLOG_ERROR, "primitives_get(): nullptr");
417 return FALSE;
418 }
419
420 pstatus_t rec = -1;
421 switch (img->fmt)
422 {
423 case AOM_IMG_FMT_I420:
424 rec = primitives->YUV420ToRGB_8u_P3AC4R(pSrc, strides, pDstData, nDstStep,
425 DstFormat, &roi);
426 break;
427 case AOM_IMG_FMT_I444:
428 rec = primitives->YUV444ToRGB_8u_P3AC4R(pSrc, strides, pDstData, nDstStep,
429 DstFormat, &roi);
430 break;
431 default:
432 WLog_Print(av1->log, WLOG_ERROR, "img->fmt %d not supported", img->fmt);
433 return -1;
434 }
435 if (rec != 0)
436 {
437 WLog_Print(av1->log, WLOG_ERROR, "I444ToABGR() %d", rec);
438 return -1;
439 }
440#endif
441 }
442
443 return TRUE;
444}
445
446BOOL freerdp_av1_context_reset(FREERDP_AV1_CONTEXT* av1, UINT32 width, UINT32 height)
447{
448 if (av1->encoder)
449 {
450 av1->ecfg.g_w = width;
451 av1->ecfg.g_h = height;
452
453 if (av1->initialized)
454 {
455 const aom_codec_err_t rc = aom_codec_destroy(&av1->ctx);
456 av1->initialized = false;
457 if (rc != AOM_CODEC_OK)
458 {
459 WLog_Print(av1->log, WLOG_WARN, "aom_codec_destroy: %s",
460 aom_codec_err_to_string(rc));
461 return FALSE;
462 }
463 }
464
465 const aom_codec_err_t rc =
466 aom_codec_enc_init(&av1->ctx, av1->iface, &av1->ecfg, av1->flags);
467 if (rc != AOM_CODEC_OK)
468 {
469 WLog_Print(av1->log, WLOG_WARN, "aom_codec_enc_init: %s", aom_codec_err_to_string(rc));
470 return FALSE;
471 }
472
473 av1->framecount = 0;
474 av1->eflags = 0; // AOM_EFLAG_FORCE_KF;
475 }
476 else
477 {
478 av1->dcfg.w = width;
479 av1->dcfg.h = height;
480 av1->dcfg.allow_lowbitdepth = 1;
481 const aom_codec_err_t rc =
482 aom_codec_dec_init(&av1->ctx, av1->iface, &av1->dcfg, av1->flags);
483 if (rc != AOM_CODEC_OK)
484 {
485 WLog_Print(av1->log, WLOG_WARN, "aom_codec_dec_init: %s", aom_codec_err_to_string(rc));
486 return FALSE;
487 }
488 }
489 av1->initialized = true;
490
491 av1->yuvWidth = width;
492 av1->yuvStride[0] = width;
493
494 const size_t pad = av1->yuvStride[0] % 16;
495 if (pad != 0)
496 av1->yuvStride[0] += 16 - pad;
497 av1->yuvStride[0] *= 3;
498 av1->yuvStride[1] = width;
499 av1->yuvStride[2] = width;
500
501 av1->yuvHeight = height;
502 winpr_aligned_free(av1->yuvdata[0]);
503 winpr_aligned_free(av1->yuvdata[1]);
504 winpr_aligned_free(av1->yuvdata[2]);
505 av1->yuvdata[0] = winpr_aligned_malloc(1ull * av1->yuvStride[0] * av1->yuvHeight, 64);
506 av1->yuvdata[1] = winpr_aligned_malloc(1ull * av1->yuvStride[1] * av1->yuvHeight, 64);
507 av1->yuvdata[2] = winpr_aligned_malloc(1ull * av1->yuvStride[2] * av1->yuvHeight, 64);
508 return av1->yuvdata[0] != nullptr;
509}
510
511void freerdp_av1_context_free(FREERDP_AV1_CONTEXT* av1)
512{
513 if (!av1)
514 return;
515
516 if (av1->initialized)
517 {
518 const aom_codec_err_t rc = aom_codec_destroy(&av1->ctx);
519 if (rc != AOM_CODEC_OK)
520 {
521 WLog_Print(av1->log, WLOG_WARN, "aom_codec_destroy: %s", aom_codec_err_to_string(rc));
522 }
523 }
524 winpr_aligned_free(av1->yuvdata[0]);
525 winpr_aligned_free(av1->yuvdata[1]);
526 winpr_aligned_free(av1->yuvdata[2]);
527 free(av1);
528}
529
530FREERDP_AV1_CONTEXT* freerdp_av1_context_new(BOOL Compressor)
531{
532 FREERDP_AV1_CONTEXT* ctx = calloc(1, sizeof(FREERDP_AV1_CONTEXT));
533 if (!ctx)
534 return nullptr;
535 ctx->encoder = Compressor;
536 ctx->log = WLog_Get(TAG);
537 if (!ctx->log)
538 goto fail;
539
540 if (Compressor)
541 {
542 ctx->iface = aom_codec_av1_cx();
543 if (!ctx->iface)
544 {
545 WLog_Print(ctx->log, WLOG_ERROR, "aom_codec_av1_cx() nullptr");
546 goto fail;
547 }
548
549 const aom_codec_err_t rc =
550 aom_codec_enc_config_default(ctx->iface, &ctx->ecfg, AOM_USAGE_REALTIME);
551 if (rc != AOM_CODEC_OK)
552 {
553 WLog_Print(ctx->log, WLOG_ERROR, "aom_codec_enc_config_default() %s",
554 aom_codec_err_to_string(rc));
555 goto fail;
556 }
557 }
558 else
559 {
560 ctx->iface = aom_codec_av1_dx();
561 if (!ctx->iface)
562 {
563 WLog_Print(ctx->log, WLOG_ERROR, "aom_codec_av1_dx() nullptr");
564 goto fail;
565 }
566 }
567
568 return ctx;
569
570fail:
571 freerdp_av1_context_free(ctx);
572 return nullptr;
573}
574#else
575
576struct S_FREERDP_AV1_CONTEXT
577{
578 BOOL Compressor;
579 wLog* log;
580};
581
582BOOL freerdp_av1_context_set_option(WINPR_ATTR_UNUSED FREERDP_AV1_CONTEXT* av1,
583 WINPR_ATTR_UNUSED FREERDP_AV1_CONTEXT_OPTION option,
584 WINPR_ATTR_UNUSED UINT32 value)
585{
586 return FALSE;
587}
588
589UINT32 freerdp_av1_context_get_option(WINPR_ATTR_UNUSED FREERDP_AV1_CONTEXT* av1,
590 WINPR_ATTR_UNUSED FREERDP_AV1_CONTEXT_OPTION option)
591{
592 return 0;
593}
594
595INT32 freerdp_av1_compress(WINPR_ATTR_UNUSED FREERDP_AV1_CONTEXT* av1,
596 WINPR_ATTR_UNUSED const BYTE* pSrcData,
597 WINPR_ATTR_UNUSED DWORD SrcFormat, WINPR_ATTR_UNUSED UINT32 nSrcStep,
598 WINPR_ATTR_UNUSED UINT32 nSrcWidth, WINPR_ATTR_UNUSED UINT32 nSrcHeight,
599 WINPR_ATTR_UNUSED const RECTANGLE_16* regionRect,
600 WINPR_ATTR_UNUSED BYTE** ppDstData, WINPR_ATTR_UNUSED UINT32* pDstSize,
601 WINPR_ATTR_UNUSED RDPGFX_H264_METABLOCK* meta)
602{
603 WINPR_ASSERT(av1);
604 WLog_Print(av1->log, WLOG_ERROR,
605 "This build does not support AV1 codec. Recompile with '-DWITH_AOM=ON'");
606 return -1;
607}
608
609INT32 freerdp_av1_decompress(WINPR_ATTR_UNUSED FREERDP_AV1_CONTEXT* av1,
610 WINPR_ATTR_UNUSED const BYTE* pSrcData,
611 WINPR_ATTR_UNUSED UINT32 SrcSize, WINPR_ATTR_UNUSED BYTE* pDstData,
612 WINPR_ATTR_UNUSED DWORD DstFormat, WINPR_ATTR_UNUSED UINT32 nDstStep,
613 WINPR_ATTR_UNUSED UINT32 nDstWidth,
614 WINPR_ATTR_UNUSED UINT32 nDstHeight,
615 WINPR_ATTR_UNUSED const RECTANGLE_16* regionRects,
616 WINPR_ATTR_UNUSED UINT32 numRegionRect)
617{
618 WINPR_ASSERT(av1);
619 WLog_Print(av1->log, WLOG_ERROR,
620 "This build does not support AV1 codec. Recompile with '-DWITH_AOM=ON'");
621 return -1;
622}
623
624BOOL freerdp_av1_context_reset(WINPR_ATTR_UNUSED FREERDP_AV1_CONTEXT* av1,
625 WINPR_ATTR_UNUSED UINT32 width, WINPR_ATTR_UNUSED UINT32 height)
626{
627 WINPR_ASSERT(av1);
628 WLog_Print(av1->log, WLOG_WARN,
629 "This build does not support AV1 codec. Recompile with '-DWITH_AOM=ON'");
630 return FALSE;
631}
632
633void freerdp_av1_context_free(WINPR_ATTR_UNUSED FREERDP_AV1_CONTEXT* av1)
634{
635 free(av1);
636}
637
638FREERDP_AV1_CONTEXT* freerdp_av1_context_new(BOOL Compressor)
639{
640 FREERDP_AV1_CONTEXT* ctx = calloc(1, sizeof(FREERDP_AV1_CONTEXT));
641 if (!ctx)
642 return nullptr;
643 ctx->Compressor = Compressor;
644 ctx->log = WLog_Get(TAG);
645 return ctx;
646}
647#endif
WINPR_ATTR_NODISCARD fn_RGBToYUV444_8u_P3AC4R_t RGBToI444_8u
Definition primitives.h:305