BOOL shadow_client_surface_frame_acknowledge(rdpShadowClient* client, UINT32 frameId)
{
- SURFACE_FRAME* frame;
- wListDictionary* frameList;
+ /*
+ * Record the last client acknowledged frame id to
+ * calculate how much frames are in progress.
+ * Some rdp clients (win7 mstsc) skips frame ACK if it is
+ * inactive, we should not expect ACK for each frame.
+ * So it is OK to calculate inflight frame count according to
+ * a latest acknowledged frame id.
+ */
+ client->encoder->lastAckframeId = frameId;
- frameList = client->encoder->frameList;
- frame = (SURFACE_FRAME*) ListDictionary_GetItemValue(frameList, (void*) (size_t) frameId);
-
- if (frame)
- {
- ListDictionary_Remove(frameList, (void*) (size_t) frameId);
- free(frame);
- }
return TRUE;
}
}
if (encoder->frameAck)
- frameId = (UINT32) shadow_encoder_create_frame_id(encoder);
+ frameId = shadow_encoder_create_frame_id(encoder);
if (settings->RemoteFxCodec)
{
#include "shadow_encoder.h"
-int shadow_encoder_create_frame_id(rdpShadowEncoder* encoder)
+int shadow_encoder_preferred_fps(rdpShadowEncoder* encoder)
+{
+ /* Return preferred fps calculated according to the last
+ * sent frame id and last client-acknowledged frame id.
+ */
+ return encoder->fps;
+}
+
+UINT32 shadow_encoder_inflight_frames(rdpShadowEncoder* encoder)
+{
+ /* Return inflight frame count =
+ * <last sent frame id> - <last client-acknowledged frame id>
+ * Note: This function is exported so that subsystem could
+ * implement its own strategy to tune fps.
+ */
+ return encoder->frameId - encoder->lastAckframeId;
+}
+
+UINT32 shadow_encoder_create_frame_id(rdpShadowEncoder* encoder)
{
UINT32 frameId;
int inFlightFrames;
- SURFACE_FRAME* frame;
- inFlightFrames = ListDictionary_Count(encoder->frameList);
+ inFlightFrames = shadow_encoder_inflight_frames(encoder);
- if (inFlightFrames > encoder->frameAck)
+ /*
+ * Calculate preferred fps according to how much frames are
+ * in-progress. Note that it only works when subsytem implementation
+ * calls shadow_encoder_preferred_fps and takes the suggestion.
+ */
+ if (inFlightFrames > 1)
{
encoder->fps = (100 / (inFlightFrames + 1) * encoder->maxFps) / 100;
}
if (encoder->fps < 1)
encoder->fps = 1;
- frame = (SURFACE_FRAME*) malloc(sizeof(SURFACE_FRAME));
+ frameId = ++encoder->frameId;
- if (!frame)
- return -1;
-
- frameId = frame->frameId = ++encoder->frameId;
- if (!ListDictionary_Add(encoder->frameList, (void*) (size_t) frame->frameId, frame))
- return -1;
-
- return (int) frame->frameId;
+ return frameId;
}
int shadow_encoder_init_grid(rdpShadowEncoder* encoder)
rfx_context_set_pixel_format(encoder->rfx, RDP_PIXEL_FORMAT_B8G8R8A8);
- if (!encoder->frameList)
- {
- encoder->fps = 16;
- encoder->maxFps = 32;
- encoder->frameId = 0;
- encoder->frameList = ListDictionary_New(TRUE);
- if (!encoder->frameList)
- return -1;
- encoder->frameAck = settings->SurfaceFrameMarkerEnabled;
- }
+ encoder->fps = 16;
+ encoder->maxFps = 32;
+ encoder->frameId = 0;
+ encoder->lastAckframeId = 0;
+ encoder->frameAck = settings->SurfaceFrameMarkerEnabled;
encoder->codecs |= FREERDP_CODEC_REMOTEFX;
nsc_context_set_pixel_format(encoder->nsc, RDP_PIXEL_FORMAT_B8G8R8A8);
- if (!encoder->frameList)
- {
- encoder->fps = 16;
- encoder->maxFps = 32;
- encoder->frameId = 0;
- encoder->frameList = ListDictionary_New(TRUE);
- if (!encoder->frameList)
- return -1;
- encoder->frameAck = settings->SurfaceFrameMarkerEnabled;
- }
+ encoder->fps = 16;
+ encoder->maxFps = 32;
+ encoder->frameId = 0;
+ encoder->lastAckframeId = 0;
+ encoder->frameAck = settings->SurfaceFrameMarkerEnabled;
encoder->nsc->ColorLossLevel = settings->NSCodecColorLossLevel;
encoder->nsc->ChromaSubsamplingLevel = settings->NSCodecAllowSubsampling ? 1 : 0;
encoder->rfx = NULL;
}
- if (encoder->frameList)
- {
- ListDictionary_Free(encoder->frameList);
- encoder->frameList = NULL;
- }
-
encoder->codecs &= ~FREERDP_CODEC_REMOTEFX;
return 1;
encoder->nsc = NULL;
}
- if (encoder->frameList)
- {
- ListDictionary_Free(encoder->frameList);
- encoder->frameList = NULL;
- }
-
encoder->codecs &= ~FREERDP_CODEC_NSCODEC;
return 1;