FreeRDP
shadow_encoder.c
1 
19 #include <freerdp/config.h>
20 
21 #include <winpr/assert.h>
22 
23 #include "shadow.h"
24 
25 #include "shadow_encoder.h"
26 
27 #include <freerdp/log.h>
28 #define TAG CLIENT_TAG("shadow")
29 
30 UINT32 shadow_encoder_preferred_fps(rdpShadowEncoder* encoder)
31 {
32  /* Return preferred fps calculated according to the last
33  * sent frame id and last client-acknowledged frame id.
34  */
35  return encoder->fps;
36 }
37 
38 UINT32 shadow_encoder_inflight_frames(rdpShadowEncoder* encoder)
39 {
40  /* Return inflight frame count.
41  * If queueDepth is SUSPEND_FRAME_ACKNOWLEDGEMENT, count = 0
42  * Otherwise, calculate count =
43  * <last sent frame id> - <last client-acknowledged frame id>
44  * Note: This function is exported so that subsystem could
45  * implement its own strategy to tune fps.
46  */
47  return (encoder->queueDepth == SUSPEND_FRAME_ACKNOWLEDGEMENT)
48  ? 0
49  : encoder->frameId - encoder->lastAckframeId;
50 }
51 
52 UINT32 shadow_encoder_create_frame_id(rdpShadowEncoder* encoder)
53 {
54  UINT32 frameId = 0;
55  UINT32 inFlightFrames = shadow_encoder_inflight_frames(encoder);
56 
57  /*
58  * Calculate preferred fps according to how much frames are
59  * in-progress. Note that it only works when subsytem implementation
60  * calls shadow_encoder_preferred_fps and takes the suggestion.
61  */
62  if (inFlightFrames > 1)
63  {
64  encoder->fps = (100 / (inFlightFrames + 1) * encoder->maxFps) / 100;
65  }
66  else
67  {
68  encoder->fps += 2;
69 
70  if (encoder->fps > encoder->maxFps)
71  encoder->fps = encoder->maxFps;
72  }
73 
74  if (encoder->fps < 1)
75  encoder->fps = 1;
76 
77  frameId = ++encoder->frameId;
78  return frameId;
79 }
80 
81 static int shadow_encoder_init_grid(rdpShadowEncoder* encoder)
82 {
83  UINT32 tileSize = 0;
84  UINT32 tileCount = 0;
85  encoder->gridWidth = ((encoder->width + (encoder->maxTileWidth - 1)) / encoder->maxTileWidth);
86  encoder->gridHeight =
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);
91 
92  if (!encoder->gridBuffer)
93  return -1;
94 
95  encoder->grid = (BYTE**)calloc(tileCount, sizeof(BYTE*));
96 
97  if (!encoder->grid)
98  return -1;
99 
100  for (UINT32 i = 0; i < encoder->gridHeight; i++)
101  {
102  for (UINT32 j = 0; j < encoder->gridWidth; j++)
103  {
104  const size_t k = (1ULL * i * encoder->gridWidth) + j;
105  encoder->grid[k] = &(encoder->gridBuffer[k * tileSize]);
106  }
107  }
108 
109  return 0;
110 }
111 
112 static int shadow_encoder_uninit_grid(rdpShadowEncoder* encoder)
113 {
114  if (encoder->gridBuffer)
115  {
116  free(encoder->gridBuffer);
117  encoder->gridBuffer = NULL;
118  }
119 
120  if (encoder->grid)
121  {
122  free(encoder->grid);
123  encoder->grid = NULL;
124  }
125 
126  encoder->gridWidth = 0;
127  encoder->gridHeight = 0;
128  return 0;
129 }
130 
131 static int shadow_encoder_init_rfx(rdpShadowEncoder* encoder)
132 {
133  if (!encoder->rfx)
134  encoder->rfx = rfx_context_new_ex(
135  TRUE, freerdp_settings_get_uint32(encoder->server->settings, FreeRDP_ThreadingFlags));
136 
137  if (!encoder->rfx)
138  goto fail;
139 
140  if (!rfx_context_reset(encoder->rfx, encoder->width, encoder->height))
141  goto fail;
142 
143  rfx_context_set_mode(encoder->rfx, freerdp_settings_get_uint32(encoder->server->settings,
144  FreeRDP_RemoteFxRlgrMode));
145  rfx_context_set_pixel_format(encoder->rfx, PIXEL_FORMAT_BGRX32);
146  encoder->codecs |= FREERDP_CODEC_REMOTEFX;
147  return 1;
148 fail:
149  rfx_context_free(encoder->rfx);
150  return -1;
151 }
152 
153 static int shadow_encoder_init_nsc(rdpShadowEncoder* encoder)
154 {
155  rdpContext* context = (rdpContext*)encoder->client;
156  rdpSettings* settings = context->settings;
157 
158  if (!encoder->nsc)
159  encoder->nsc = nsc_context_new();
160 
161  if (!encoder->nsc)
162  goto fail;
163 
164  if (!nsc_context_reset(encoder->nsc, encoder->width, encoder->height))
165  goto fail;
166 
167  if (!nsc_context_set_parameters(
168  encoder->nsc, NSC_COLOR_LOSS_LEVEL,
169  freerdp_settings_get_uint32(settings, FreeRDP_NSCodecColorLossLevel)))
170  goto fail;
171  if (!nsc_context_set_parameters(
172  encoder->nsc, NSC_ALLOW_SUBSAMPLING,
173  freerdp_settings_get_bool(settings, FreeRDP_NSCodecAllowSubsampling)))
174  goto fail;
175  if (!nsc_context_set_parameters(
176  encoder->nsc, NSC_DYNAMIC_COLOR_FIDELITY,
177  !freerdp_settings_get_bool(settings, FreeRDP_NSCodecAllowDynamicColorFidelity)))
178  goto fail;
179  if (!nsc_context_set_parameters(encoder->nsc, NSC_COLOR_FORMAT, PIXEL_FORMAT_BGRX32))
180  goto fail;
181  encoder->codecs |= FREERDP_CODEC_NSCODEC;
182  return 1;
183 fail:
184  nsc_context_free(encoder->nsc);
185  return -1;
186 }
187 
188 static int shadow_encoder_init_planar(rdpShadowEncoder* encoder)
189 {
190  DWORD planarFlags = 0;
191  rdpContext* context = (rdpContext*)encoder->client;
192  rdpSettings* settings = context->settings;
193 
194  if (freerdp_settings_get_bool(settings, FreeRDP_DrawAllowSkipAlpha))
195  planarFlags |= PLANAR_FORMAT_HEADER_NA;
196 
197  planarFlags |= PLANAR_FORMAT_HEADER_RLE;
198 
199  if (!encoder->planar)
200  {
201  encoder->planar = freerdp_bitmap_planar_context_new(planarFlags, encoder->maxTileWidth,
202  encoder->maxTileHeight);
203  }
204 
205  if (!encoder->planar)
206  goto fail;
207 
208  if (!freerdp_bitmap_planar_context_reset(encoder->planar, encoder->maxTileWidth,
209  encoder->maxTileHeight))
210  goto fail;
211 
212  encoder->codecs |= FREERDP_CODEC_PLANAR;
213  return 1;
214 fail:
215  freerdp_bitmap_planar_context_free(encoder->planar);
216  return -1;
217 }
218 
219 static int shadow_encoder_init_interleaved(rdpShadowEncoder* encoder)
220 {
221  if (!encoder->interleaved)
222  encoder->interleaved = bitmap_interleaved_context_new(TRUE);
223 
224  if (!encoder->interleaved)
225  goto fail;
226 
227  if (!bitmap_interleaved_context_reset(encoder->interleaved))
228  goto fail;
229 
230  encoder->codecs |= FREERDP_CODEC_INTERLEAVED;
231  return 1;
232 fail:
233  bitmap_interleaved_context_free(encoder->interleaved);
234  return -1;
235 }
236 
237 static int shadow_encoder_init_h264(rdpShadowEncoder* encoder)
238 {
239  if (!encoder->h264)
240  encoder->h264 = h264_context_new(TRUE);
241 
242  if (!encoder->h264)
243  goto fail;
244 
245  if (!h264_context_reset(encoder->h264, encoder->width, encoder->height))
246  goto fail;
247 
248  if (!h264_context_set_option(encoder->h264, H264_CONTEXT_OPTION_RATECONTROL,
249  encoder->server->h264RateControlMode))
250  goto fail;
251  if (!h264_context_set_option(encoder->h264, H264_CONTEXT_OPTION_BITRATE,
252  encoder->server->h264BitRate))
253  goto fail;
254  if (!h264_context_set_option(encoder->h264, H264_CONTEXT_OPTION_FRAMERATE,
255  encoder->server->h264FrameRate))
256  goto fail;
257  if (!h264_context_set_option(encoder->h264, H264_CONTEXT_OPTION_QP, encoder->server->h264QP))
258  goto fail;
259 
260  encoder->codecs |= FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444;
261  return 1;
262 fail:
263  h264_context_free(encoder->h264);
264  return -1;
265 }
266 
267 static int shadow_encoder_init_progressive(rdpShadowEncoder* encoder)
268 {
269  WINPR_ASSERT(encoder);
270  if (!encoder->progressive)
271  encoder->progressive = progressive_context_new(TRUE);
272 
273  if (!encoder->progressive)
274  goto fail;
275 
276  if (!progressive_context_reset(encoder->progressive))
277  goto fail;
278 
279  encoder->codecs |= FREERDP_CODEC_PROGRESSIVE;
280  return 1;
281 fail:
282  progressive_context_free(encoder->progressive);
283  return -1;
284 }
285 
286 static int shadow_encoder_init(rdpShadowEncoder* encoder)
287 {
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);
293 
294  if (!encoder->bs)
295  encoder->bs = Stream_New(NULL, 4ULL * encoder->maxTileWidth * encoder->maxTileHeight);
296 
297  if (!encoder->bs)
298  return -1;
299 
300  return 1;
301 }
302 
303 static int shadow_encoder_uninit_rfx(rdpShadowEncoder* encoder)
304 {
305  if (encoder->rfx)
306  {
307  rfx_context_free(encoder->rfx);
308  encoder->rfx = NULL;
309  }
310 
311  encoder->codecs &= (UINT32)~FREERDP_CODEC_REMOTEFX;
312  return 1;
313 }
314 
315 static int shadow_encoder_uninit_nsc(rdpShadowEncoder* encoder)
316 {
317  if (encoder->nsc)
318  {
319  nsc_context_free(encoder->nsc);
320  encoder->nsc = NULL;
321  }
322 
323  encoder->codecs &= (UINT32)~FREERDP_CODEC_NSCODEC;
324  return 1;
325 }
326 
327 static int shadow_encoder_uninit_planar(rdpShadowEncoder* encoder)
328 {
329  if (encoder->planar)
330  {
331  freerdp_bitmap_planar_context_free(encoder->planar);
332  encoder->planar = NULL;
333  }
334 
335  encoder->codecs &= (UINT32)~FREERDP_CODEC_PLANAR;
336  return 1;
337 }
338 
339 static int shadow_encoder_uninit_interleaved(rdpShadowEncoder* encoder)
340 {
341  if (encoder->interleaved)
342  {
343  bitmap_interleaved_context_free(encoder->interleaved);
344  encoder->interleaved = NULL;
345  }
346 
347  encoder->codecs &= (UINT32)~FREERDP_CODEC_INTERLEAVED;
348  return 1;
349 }
350 
351 static int shadow_encoder_uninit_h264(rdpShadowEncoder* encoder)
352 {
353  if (encoder->h264)
354  {
355  h264_context_free(encoder->h264);
356  encoder->h264 = NULL;
357  }
358 
359  encoder->codecs &= (UINT32) ~(FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444);
360  return 1;
361 }
362 
363 static int shadow_encoder_uninit_progressive(rdpShadowEncoder* encoder)
364 {
365  WINPR_ASSERT(encoder);
366  if (encoder->progressive)
367  {
368  progressive_context_free(encoder->progressive);
369  encoder->progressive = NULL;
370  }
371 
372  encoder->codecs &= (UINT32)~FREERDP_CODEC_PROGRESSIVE;
373  return 1;
374 }
375 
376 static int shadow_encoder_uninit(rdpShadowEncoder* encoder)
377 {
378  shadow_encoder_uninit_grid(encoder);
379 
380  if (encoder->bs)
381  {
382  Stream_Free(encoder->bs, TRUE);
383  encoder->bs = NULL;
384  }
385 
386  shadow_encoder_uninit_rfx(encoder);
387 
388  shadow_encoder_uninit_nsc(encoder);
389 
390  shadow_encoder_uninit_planar(encoder);
391 
392  shadow_encoder_uninit_interleaved(encoder);
393  shadow_encoder_uninit_h264(encoder);
394 
395  shadow_encoder_uninit_progressive(encoder);
396 
397  return 1;
398 }
399 
400 int shadow_encoder_reset(rdpShadowEncoder* encoder)
401 {
402  int status = 0;
403  UINT32 codecs = encoder->codecs;
404  rdpContext* context = (rdpContext*)encoder->client;
405  rdpSettings* settings = context->settings;
406  status = shadow_encoder_uninit(encoder);
407 
408  if (status < 0)
409  return -1;
410 
411  status = shadow_encoder_init(encoder);
412 
413  if (status < 0)
414  return -1;
415 
416  status = shadow_encoder_prepare(encoder, codecs);
417 
418  if (status < 0)
419  return -1;
420 
421  encoder->fps = 16;
422  encoder->maxFps = 32;
423  encoder->frameId = 0;
424  encoder->lastAckframeId = 0;
425  encoder->frameAck = freerdp_settings_get_bool(settings, FreeRDP_SurfaceFrameMarkerEnabled);
426  return 1;
427 }
428 
429 int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs)
430 {
431  int status = 0;
432 
433  if ((codecs & FREERDP_CODEC_REMOTEFX) && !(encoder->codecs & FREERDP_CODEC_REMOTEFX))
434  {
435  WLog_DBG(TAG, "initializing RemoteFX encoder");
436  status = shadow_encoder_init_rfx(encoder);
437 
438  if (status < 0)
439  return -1;
440  }
441 
442  if ((codecs & FREERDP_CODEC_NSCODEC) && !(encoder->codecs & FREERDP_CODEC_NSCODEC))
443  {
444  WLog_DBG(TAG, "initializing NSCodec encoder");
445  status = shadow_encoder_init_nsc(encoder);
446 
447  if (status < 0)
448  return -1;
449  }
450 
451  if ((codecs & FREERDP_CODEC_PLANAR) && !(encoder->codecs & FREERDP_CODEC_PLANAR))
452  {
453  WLog_DBG(TAG, "initializing planar bitmap encoder");
454  status = shadow_encoder_init_planar(encoder);
455 
456  if (status < 0)
457  return -1;
458  }
459 
460  if ((codecs & FREERDP_CODEC_INTERLEAVED) && !(encoder->codecs & FREERDP_CODEC_INTERLEAVED))
461  {
462  WLog_DBG(TAG, "initializing interleaved bitmap encoder");
463  status = shadow_encoder_init_interleaved(encoder);
464 
465  if (status < 0)
466  return -1;
467  }
468 
469  if ((codecs & (FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444)) &&
470  !(encoder->codecs & (FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444)))
471  {
472  WLog_DBG(TAG, "initializing H.264 encoder");
473  status = shadow_encoder_init_h264(encoder);
474 
475  if (status < 0)
476  return -1;
477  }
478 
479  if ((codecs & FREERDP_CODEC_PROGRESSIVE) && !(encoder->codecs & FREERDP_CODEC_PROGRESSIVE))
480  {
481  WLog_DBG(TAG, "initializing progressive encoder");
482  status = shadow_encoder_init_progressive(encoder);
483 
484  if (status < 0)
485  return -1;
486  }
487 
488  return 1;
489 }
490 
491 rdpShadowEncoder* shadow_encoder_new(rdpShadowClient* client)
492 {
493  rdpShadowEncoder* encoder = NULL;
494  rdpShadowServer* server = client->server;
495  encoder = (rdpShadowEncoder*)calloc(1, sizeof(rdpShadowEncoder));
496 
497  if (!encoder)
498  return NULL;
499 
500  encoder->client = client;
501  encoder->server = server;
502  encoder->fps = 16;
503  encoder->maxFps = 32;
504 
505  if (shadow_encoder_init(encoder) < 0)
506  {
507  free(encoder);
508  return NULL;
509  }
510 
511  return encoder;
512 }
513 
514 void shadow_encoder_free(rdpShadowEncoder* encoder)
515 {
516  if (!encoder)
517  return;
518 
519  shadow_encoder_uninit(encoder);
520  free(encoder);
521 }
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.