19 #include <freerdp/config.h>
21 #include <winpr/assert.h>
25 #include "shadow_encoder.h"
27 #include <freerdp/log.h>
28 #define TAG CLIENT_TAG("shadow")
30 UINT32 shadow_encoder_preferred_fps(rdpShadowEncoder* encoder)
38 UINT32 shadow_encoder_inflight_frames(rdpShadowEncoder* encoder)
47 return (encoder->queueDepth == SUSPEND_FRAME_ACKNOWLEDGEMENT)
49 : encoder->frameId - encoder->lastAckframeId;
52 UINT32 shadow_encoder_create_frame_id(rdpShadowEncoder* encoder)
55 UINT32 inFlightFrames = shadow_encoder_inflight_frames(encoder);
62 if (inFlightFrames > 1)
64 encoder->fps = (100 / (inFlightFrames + 1) * encoder->maxFps) / 100;
70 if (encoder->fps > encoder->maxFps)
71 encoder->fps = encoder->maxFps;
77 frameId = ++encoder->frameId;
81 static int shadow_encoder_init_grid(rdpShadowEncoder* encoder)
85 encoder->gridWidth = ((encoder->width + (encoder->maxTileWidth - 1)) / encoder->maxTileWidth);
87 ((encoder->height + (encoder->maxTileHeight - 1)) / encoder->maxTileHeight);
88 tileSize = encoder->maxTileWidth * encoder->maxTileHeight * 4;
89 tileCount = encoder->gridWidth * encoder->gridHeight;
90 encoder->gridBuffer = (BYTE*)calloc(tileSize, tileCount);
92 if (!encoder->gridBuffer)
95 encoder->grid = (BYTE**)calloc(tileCount,
sizeof(BYTE*));
100 for (UINT32 i = 0; i < encoder->gridHeight; i++)
102 for (UINT32 j = 0; j < encoder->gridWidth; j++)
104 const size_t k = (1ULL * i * encoder->gridWidth) + j;
105 encoder->grid[k] = &(encoder->gridBuffer[k * tileSize]);
112 static int shadow_encoder_uninit_grid(rdpShadowEncoder* encoder)
114 if (encoder->gridBuffer)
116 free(encoder->gridBuffer);
117 encoder->gridBuffer = NULL;
123 encoder->grid = NULL;
126 encoder->gridWidth = 0;
127 encoder->gridHeight = 0;
131 static int shadow_encoder_init_rfx(rdpShadowEncoder* encoder)
134 encoder->rfx = rfx_context_new_ex(
140 if (!rfx_context_reset(encoder->rfx, encoder->width, encoder->height))
144 FreeRDP_RemoteFxRlgrMode));
145 rfx_context_set_pixel_format(encoder->rfx, PIXEL_FORMAT_BGRX32);
146 encoder->codecs |= FREERDP_CODEC_REMOTEFX;
149 rfx_context_free(encoder->rfx);
153 static int shadow_encoder_init_nsc(rdpShadowEncoder* encoder)
155 rdpContext* context = (rdpContext*)encoder->client;
156 rdpSettings* settings = context->settings;
159 encoder->nsc = nsc_context_new();
164 if (!nsc_context_reset(encoder->nsc, encoder->width, encoder->height))
167 if (!nsc_context_set_parameters(
168 encoder->nsc, NSC_COLOR_LOSS_LEVEL,
171 if (!nsc_context_set_parameters(
172 encoder->nsc, NSC_ALLOW_SUBSAMPLING,
175 if (!nsc_context_set_parameters(
176 encoder->nsc, NSC_DYNAMIC_COLOR_FIDELITY,
179 if (!nsc_context_set_parameters(encoder->nsc, NSC_COLOR_FORMAT, PIXEL_FORMAT_BGRX32))
181 encoder->codecs |= FREERDP_CODEC_NSCODEC;
184 nsc_context_free(encoder->nsc);
188 static int shadow_encoder_init_planar(rdpShadowEncoder* encoder)
190 DWORD planarFlags = 0;
191 rdpContext* context = (rdpContext*)encoder->client;
192 rdpSettings* settings = context->settings;
195 planarFlags |= PLANAR_FORMAT_HEADER_NA;
197 planarFlags |= PLANAR_FORMAT_HEADER_RLE;
199 if (!encoder->planar)
201 encoder->planar = freerdp_bitmap_planar_context_new(planarFlags, encoder->maxTileWidth,
202 encoder->maxTileHeight);
205 if (!encoder->planar)
208 if (!freerdp_bitmap_planar_context_reset(encoder->planar, encoder->maxTileWidth,
209 encoder->maxTileHeight))
212 encoder->codecs |= FREERDP_CODEC_PLANAR;
215 freerdp_bitmap_planar_context_free(encoder->planar);
219 static int shadow_encoder_init_interleaved(rdpShadowEncoder* encoder)
221 if (!encoder->interleaved)
222 encoder->interleaved = bitmap_interleaved_context_new(TRUE);
224 if (!encoder->interleaved)
227 if (!bitmap_interleaved_context_reset(encoder->interleaved))
230 encoder->codecs |= FREERDP_CODEC_INTERLEAVED;
233 bitmap_interleaved_context_free(encoder->interleaved);
237 static int shadow_encoder_init_h264(rdpShadowEncoder* encoder)
240 encoder->h264 = h264_context_new(TRUE);
245 if (!h264_context_reset(encoder->h264, encoder->width, encoder->height))
248 if (!h264_context_set_option(encoder->h264, H264_CONTEXT_OPTION_RATECONTROL,
249 encoder->server->h264RateControlMode))
251 if (!h264_context_set_option(encoder->h264, H264_CONTEXT_OPTION_BITRATE,
252 encoder->server->h264BitRate))
254 if (!h264_context_set_option(encoder->h264, H264_CONTEXT_OPTION_FRAMERATE,
255 encoder->server->h264FrameRate))
257 if (!h264_context_set_option(encoder->h264, H264_CONTEXT_OPTION_QP, encoder->server->h264QP))
260 encoder->codecs |= FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444;
263 h264_context_free(encoder->h264);
267 static int shadow_encoder_init_progressive(rdpShadowEncoder* encoder)
269 WINPR_ASSERT(encoder);
270 if (!encoder->progressive)
271 encoder->progressive = progressive_context_new(TRUE);
273 if (!encoder->progressive)
276 if (!progressive_context_reset(encoder->progressive))
279 encoder->codecs |= FREERDP_CODEC_PROGRESSIVE;
282 progressive_context_free(encoder->progressive);
286 static int shadow_encoder_init(rdpShadowEncoder* encoder)
288 encoder->width = encoder->server->screen->width;
289 encoder->height = encoder->server->screen->height;
290 encoder->maxTileWidth = 64;
291 encoder->maxTileHeight = 64;
292 shadow_encoder_init_grid(encoder);
295 encoder->bs = Stream_New(NULL, 4ULL * encoder->maxTileWidth * encoder->maxTileHeight);
303 static int shadow_encoder_uninit_rfx(rdpShadowEncoder* encoder)
307 rfx_context_free(encoder->rfx);
311 encoder->codecs &= (UINT32)~FREERDP_CODEC_REMOTEFX;
315 static int shadow_encoder_uninit_nsc(rdpShadowEncoder* encoder)
319 nsc_context_free(encoder->nsc);
323 encoder->codecs &= (UINT32)~FREERDP_CODEC_NSCODEC;
327 static int shadow_encoder_uninit_planar(rdpShadowEncoder* encoder)
331 freerdp_bitmap_planar_context_free(encoder->planar);
332 encoder->planar = NULL;
335 encoder->codecs &= (UINT32)~FREERDP_CODEC_PLANAR;
339 static int shadow_encoder_uninit_interleaved(rdpShadowEncoder* encoder)
341 if (encoder->interleaved)
343 bitmap_interleaved_context_free(encoder->interleaved);
344 encoder->interleaved = NULL;
347 encoder->codecs &= (UINT32)~FREERDP_CODEC_INTERLEAVED;
351 static int shadow_encoder_uninit_h264(rdpShadowEncoder* encoder)
355 h264_context_free(encoder->h264);
356 encoder->h264 = NULL;
359 encoder->codecs &= (UINT32) ~(FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444);
363 static int shadow_encoder_uninit_progressive(rdpShadowEncoder* encoder)
365 WINPR_ASSERT(encoder);
366 if (encoder->progressive)
368 progressive_context_free(encoder->progressive);
369 encoder->progressive = NULL;
372 encoder->codecs &= (UINT32)~FREERDP_CODEC_PROGRESSIVE;
376 static int shadow_encoder_uninit(rdpShadowEncoder* encoder)
378 shadow_encoder_uninit_grid(encoder);
382 Stream_Free(encoder->bs, TRUE);
386 shadow_encoder_uninit_rfx(encoder);
388 shadow_encoder_uninit_nsc(encoder);
390 shadow_encoder_uninit_planar(encoder);
392 shadow_encoder_uninit_interleaved(encoder);
393 shadow_encoder_uninit_h264(encoder);
395 shadow_encoder_uninit_progressive(encoder);
400 int shadow_encoder_reset(rdpShadowEncoder* encoder)
403 UINT32 codecs = encoder->codecs;
404 rdpContext* context = (rdpContext*)encoder->client;
405 rdpSettings* settings = context->settings;
406 status = shadow_encoder_uninit(encoder);
411 status = shadow_encoder_init(encoder);
416 status = shadow_encoder_prepare(encoder, codecs);
422 encoder->maxFps = 32;
423 encoder->frameId = 0;
424 encoder->lastAckframeId = 0;
429 int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs)
433 if ((codecs & FREERDP_CODEC_REMOTEFX) && !(encoder->codecs & FREERDP_CODEC_REMOTEFX))
435 WLog_DBG(TAG,
"initializing RemoteFX encoder");
436 status = shadow_encoder_init_rfx(encoder);
442 if ((codecs & FREERDP_CODEC_NSCODEC) && !(encoder->codecs & FREERDP_CODEC_NSCODEC))
444 WLog_DBG(TAG,
"initializing NSCodec encoder");
445 status = shadow_encoder_init_nsc(encoder);
451 if ((codecs & FREERDP_CODEC_PLANAR) && !(encoder->codecs & FREERDP_CODEC_PLANAR))
453 WLog_DBG(TAG,
"initializing planar bitmap encoder");
454 status = shadow_encoder_init_planar(encoder);
460 if ((codecs & FREERDP_CODEC_INTERLEAVED) && !(encoder->codecs & FREERDP_CODEC_INTERLEAVED))
462 WLog_DBG(TAG,
"initializing interleaved bitmap encoder");
463 status = shadow_encoder_init_interleaved(encoder);
469 if ((codecs & (FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444)) &&
470 !(encoder->codecs & (FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444)))
472 WLog_DBG(TAG,
"initializing H.264 encoder");
473 status = shadow_encoder_init_h264(encoder);
479 if ((codecs & FREERDP_CODEC_PROGRESSIVE) && !(encoder->codecs & FREERDP_CODEC_PROGRESSIVE))
481 WLog_DBG(TAG,
"initializing progressive encoder");
482 status = shadow_encoder_init_progressive(encoder);
491 rdpShadowEncoder* shadow_encoder_new(rdpShadowClient* client)
493 rdpShadowEncoder* encoder = NULL;
494 rdpShadowServer* server = client->server;
495 encoder = (rdpShadowEncoder*)calloc(1,
sizeof(rdpShadowEncoder));
500 encoder->client = client;
501 encoder->server = server;
503 encoder->maxFps = 32;
505 if (shadow_encoder_init(encoder) < 0)
514 void shadow_encoder_free(rdpShadowEncoder* encoder)
519 shadow_encoder_uninit(encoder);
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.