FreeRDP
wf_update.c
1 
21 #include <freerdp/config.h>
22 
23 #include <stdio.h>
24 
25 #include <winpr/windows.h>
26 
27 #include <freerdp/freerdp.h>
28 #include <freerdp/listener.h>
29 
30 #include "wf_peer.h"
31 #include "wf_info.h"
32 #include "wf_mirage.h"
33 
34 #include "wf_update.h"
35 
36 #include <freerdp/log.h>
37 #define TAG SERVER_TAG("windows")
38 
39 DWORD WINAPI wf_update_thread(LPVOID lpParam)
40 {
41  DWORD fps;
42  wfInfo* wfi;
43  DWORD beg, end;
44  DWORD diff, rate;
45  wfi = (wfInfo*)lpParam;
46  fps = wfi->framesPerSecond;
47  rate = 1000 / fps;
48 
49  while (1)
50  {
51  beg = GetTickCount();
52 
53  if (wf_info_lock(wfi) > 0)
54  {
55  if (wfi->activePeerCount > 0)
56  {
57  wf_info_update_changes(wfi);
58 
59  if (wf_info_have_updates(wfi))
60  {
61  wf_update_encode(wfi);
62  // WLog_DBG(TAG, "Start of parallel sending");
63  int index = 0;
64 
65  for (int peerindex = 0; peerindex < wfi->peerCount; peerindex++)
66  {
67  for (; index < FREERDP_SERVER_WIN_INFO_MAXPEERS; index++)
68  {
69  if (wfi->peers[index] && wfi->peers[index]->activated)
70  {
71  // WLog_DBG(TAG, "Setting event for %d of %d", index + 1,
72  // wfi->activePeerCount);
73  (void)SetEvent(
74  ((wfPeerContext*)wfi->peers[index]->context)->updateEvent);
75  }
76  }
77  }
78 
79  for (int index = 0; index < wfi->activePeerCount; index++)
80  {
81  // WLog_DBG(TAG, "Waiting for %d of %d", index + 1, wfi->activePeerCount);
82  // WaitForSingleObject(wfi->updateSemaphore, INFINITE);
83  (void)WaitForSingleObject(wfi->updateSemaphore, 1000);
84  }
85 
86  // WLog_DBG(TAG, "End of parallel sending");
87  wf_info_clear_invalid_region(wfi);
88  }
89  }
90 
91  wf_info_unlock(wfi);
92  }
93 
94  end = GetTickCount();
95  diff = end - beg;
96 
97  if (diff < rate)
98  {
99  Sleep(rate - diff);
100  }
101  }
102 
103  // WLog_DBG(TAG, "Exiting Update Thread");
104  return 0;
105 }
106 
107 void wf_update_encode(wfInfo* wfi)
108 {
109  RFX_RECT rect;
110  long height, width;
111  BYTE* pDataBits = NULL;
112  int stride;
114  wf_info_find_invalid_region(wfi);
115  cmd = &wfi->cmd;
116  Stream_SetPosition(wfi->s, 0);
117  wf_info_getScreenData(wfi, &width, &height, &pDataBits, &stride);
118  rect.x = 0;
119  rect.y = 0;
120  rect.width = (UINT16)width;
121  rect.height = (UINT16)height;
122  // WLog_DBG(TAG, "x:%"PRId32" y:%"PRId32" w:%ld h:%ld", wfi->invalid.left, wfi->invalid.top,
123  // width, height);
124  Stream_Clear(wfi->s);
125 
126  if (!(rfx_compose_message(wfi->rfx_context, wfi->s, &rect, 1, pDataBits, width, height,
127  stride)))
128  {
129  return;
130  }
131 
132  wfi->frame_idx = rfx_context_get_frame_idx(wfi->rfx_context);
133  cmd->destLeft = wfi->invalid.left;
134  cmd->destTop = wfi->invalid.top;
135  cmd->destRight = wfi->invalid.left + width;
136  cmd->destBottom = wfi->invalid.top + height;
137  cmd->bmp.bpp = 32;
138  cmd->bmp.codecID = 3;
139  cmd->bmp.width = width;
140  cmd->bmp.height = height;
141  cmd->bmp.bitmapDataLength = Stream_GetPosition(wfi->s);
142  cmd->bmp.bitmapData = Stream_Buffer(wfi->s);
143 }
144 
145 void wf_update_peer_send(wfInfo* wfi, wfPeerContext* context)
146 {
147  freerdp_peer* client;
148 
149  WINPR_ASSERT(wfi);
150  WINPR_ASSERT(context);
151 
152  client = ((rdpContext*)context)->peer;
153  WINPR_ASSERT(client);
154 
155  /* This happens when the RemoteFX encoder state is reset */
156 
157  if (wfi->frame_idx == 1)
158  context->frame_idx = 0;
159 
160  /*
161  * When a new client connects, it is possible that old frames from
162  * from a previous encoding state remain. Those frames should be discarded
163  * as they will cause an error condition in mstsc.
164  */
165 
166  if ((context->frame_idx + 1) != wfi->frame_idx)
167  {
168  /* This frame is meant to be discarded */
169  if (context->frame_idx == 0)
170  return;
171 
172  /* This is an unexpected error condition */
173  WLog_DBG(TAG, "Unexpected Frame Index: Actual: %d Expected: %d", wfi->frame_idx,
174  context->frame_idx + 1);
175  }
176 
177  WINPR_ASSERT(client->context);
178  WINPR_ASSERT(client->context->settings);
179  WINPR_ASSERT(client->context->update);
180  WINPR_ASSERT(client->context->update->SurfaceBits);
181 
182  wfi->cmd.bmp.codecID =
183  freerdp_settings_get_uint32(client->context->settings, FreeRDP_RemoteFxCodecId);
184  client->context->update->SurfaceBits(client->context, &wfi->cmd);
185  context->frame_idx++;
186 }
187 
188 void wf_update_encoder_reset(wfInfo* wfi)
189 {
190  if (wf_info_lock(wfi) > 0)
191  {
192  WLog_DBG(TAG, "Resetting encoder");
193 
194  if (wfi->rfx_context)
195  {
196  rfx_context_reset(wfi->rfx_context, wfi->servscreen_width, wfi->servscreen_height);
197  }
198  else
199  {
200  /* TODO: pass ThreadingFlags somehow */
201  wfi->rfx_context = rfx_context_new(TRUE);
202  rfx_context_set_mode(wfi->rfx_context, RLGR3);
203  rfx_context_reset(wfi->rfx_context, wfi->servscreen_width, wfi->servscreen_height);
204  rfx_context_set_pixel_format(wfi->rfx_context, PIXEL_FORMAT_BGRA32);
205  wfi->s = Stream_New(NULL, 0xFFFF);
206  }
207 
208  wf_info_invalidate_full_screen(wfi);
209  wf_info_unlock(wfi);
210  }
211 }
212 
213 void wf_update_peer_activate(wfInfo* wfi, wfPeerContext* context)
214 {
215  if (wf_info_lock(wfi) > 0)
216  {
217  if (wfi->activePeerCount < 1)
218  {
219 #ifndef WITH_DXGI_1_2
220  wf_mirror_driver_activate(wfi);
221 #endif
222  ResumeThread(wfi->updateThread);
223  }
224 
225  wf_update_encoder_reset(wfi);
226  wfi->activePeerCount++;
227  WLog_DBG(TAG, "Activating Peer Updates: %d", wfi->activePeerCount);
228  wf_info_unlock(wfi);
229  }
230 }
231 
232 void wf_update_peer_deactivate(wfInfo* wfi, wfPeerContext* context)
233 {
234  if (wf_info_lock(wfi) > 0)
235  {
236  freerdp_peer* client = ((rdpContext*)context)->peer;
237 
238  if (client->activated)
239  {
240  if (wfi->activePeerCount <= 1)
241  {
242  wf_mirror_driver_deactivate(wfi);
243  }
244 
245  client->activated = FALSE;
246  wfi->activePeerCount--;
247  WLog_DBG(TAG, "Deactivating Peer Updates: %d", wfi->activePeerCount);
248  }
249 
250  wf_info_unlock(wfi);
251  }
252 }
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
Definition: rfx.h:44