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") 
   30UINT32 shadow_encoder_preferred_fps(rdpShadowEncoder* encoder)
 
   38UINT32 shadow_encoder_inflight_frames(rdpShadowEncoder* encoder)
 
   47  return (encoder->queueDepth == SUSPEND_FRAME_ACKNOWLEDGEMENT)
 
   49             : encoder->frameId - encoder->lastAckframeId;
 
   52UINT32 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;
 
   81static 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]);
 
  112static int shadow_encoder_uninit_grid(rdpShadowEncoder* encoder)
 
  114  if (encoder->gridBuffer)
 
  116    free(encoder->gridBuffer);
 
  117    encoder->gridBuffer = NULL;
 
  122    free((
void*)encoder->grid);
 
  123    encoder->grid = NULL;
 
  126  encoder->gridWidth = 0;
 
  127  encoder->gridHeight = 0;
 
  131static 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);
 
  153static 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);
 
  188static 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);
 
  219static 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);
 
  237static 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);
 
  267static 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);
 
  286static 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);
 
  303static int shadow_encoder_uninit_rfx(rdpShadowEncoder* encoder)
 
  307    rfx_context_free(encoder->rfx);
 
  311  encoder->codecs &= (UINT32)~FREERDP_CODEC_REMOTEFX;
 
  315static int shadow_encoder_uninit_nsc(rdpShadowEncoder* encoder)
 
  319    nsc_context_free(encoder->nsc);
 
  323  encoder->codecs &= (UINT32)~FREERDP_CODEC_NSCODEC;
 
  327static 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;
 
  339static 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;
 
  351static 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);
 
  363static 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;
 
  376static 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);
 
  400int 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;
 
  429int 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);
 
  491rdpShadowEncoder* 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)
 
  507    shadow_encoder_free(encoder);
 
  514void 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.