From 33167a7c746de49e735e76c5662d1e6c36bd10ed Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Sat, 28 Mar 2015 18:34:25 -0700 Subject: [PATCH] add frame acks and h264 codec mode basics --- common/xrdp_client_info.h | 8 ++ common/xrdp_constants.h | 4 + libxrdp/libxrdp.c | 39 +++++++- libxrdp/libxrdpinc.h | 3 + libxrdp/xrdp_caps.c | 29 ++++++ libxrdp/xrdp_fastpath.c | 25 ++--- libxrdp/xrdp_rdp.c | 21 ++++ xrdp/xrdp.h | 2 + xrdp/xrdp_encoder.c | 202 +++++++++++++++++++++----------------- xrdp/xrdp_encoder.h | 62 +++++++++++- xrdp/xrdp_mm.c | 159 +++++++++++++++++++----------- xrdp/xrdp_types.h | 49 +-------- xrdp/xrdp_wm.c | 8 +- 13 files changed, 400 insertions(+), 211 deletions(-) diff --git a/common/xrdp_client_info.h b/common/xrdp_client_info.h index 8313d0ae..d1ce1e1e 100644 --- a/common/xrdp_client_info.h +++ b/common/xrdp_client_info.h @@ -134,6 +134,14 @@ struct xrdp_client_info char variant[16]; char options[256]; + /* codec */ + int h264_codec_id; + int h264_prop_len; + char h264_prop[64]; + + int use_frame_acks; + int max_unacknowledged_frame_count; + }; #endif diff --git a/common/xrdp_constants.h b/common/xrdp_constants.h index 25d9495f..b8739b2b 100644 --- a/common/xrdp_constants.h +++ b/common/xrdp_constants.h @@ -557,6 +557,10 @@ #define XR_CODEC_GUID_PNG \ "\x8D\x85\x0C\x0E\xE0\x28\xDB\x45\xAD\xAA\x0F\x83\xE5\x7C\xC5\x60" +/* MFVideoFormat_H264 ({34363248-0000-0010-8000-00AA00389B71}) */ +#define XR_CODEC_GUID_H264 \ + "\x48\x32\x36\x34\x00\x00\x10\x00\x80\x00\x00\xAA\x00\x38\x9B\x71" + #define RDP_CAPSET_SURFCMDS 0x1c #define RDP_CAPLEN_SURFCMDS 0x0c #define RDP_CAPSET_BMPCODECS 0x1d diff --git a/libxrdp/libxrdp.c b/libxrdp/libxrdp.c index 594fcc73..32ee2098 100644 --- a/libxrdp/libxrdp.c +++ b/libxrdp/libxrdp.c @@ -1312,7 +1312,7 @@ libxrdp_fastpath_send_surface(struct xrdp_session *session, int max_bytes; int cmd_bytes; - LLOGLN(10, ("libxrdp_fastpath_init:")); + LLOGLN(10, ("libxrdp_fastpath_send_surface:")); if ((session->client_info->use_fast_path & 1) == 0) { return 1; @@ -1362,3 +1362,40 @@ libxrdp_fastpath_send_surface(struct xrdp_session *session, } return 0; } + +/*****************************************************************************/ +int EXPORT_CC +libxrdp_fastpath_send_frame_marker(struct xrdp_session *session, + int frame_action, int frame_id) +{ + struct stream *s; + struct xrdp_rdp *rdp; + + LLOGLN(10, ("libxrdp_fastpath_send_frame_marker:")); + if ((session->client_info->use_fast_path & 1) == 0) + { + return 1; + } + if (session->client_info->use_frame_acks == 0) + { + return 1; + } + rdp = (struct xrdp_rdp *) (session->rdp); + make_stream(s); + init_stream(s, 8192); + xrdp_rdp_init_fastpath(rdp, s); + out_uint16_le(s, 0x0004); /* CMDTYPE_FRAME_MARKER */ + out_uint16_le(s, frame_action); + out_uint32_le(s, frame_id); + s_mark_end(s); + /* 4 = FASTPATH_UPDATETYPE_SURFCMDS */ + if (xrdp_rdp_send_fastpath(rdp, s, 4) != 0) + { + free_stream(s); + return 1; + } + free_stream(s); + return 0; + +} + diff --git a/libxrdp/libxrdpinc.h b/libxrdp/libxrdpinc.h index 2262f66f..8d99814c 100644 --- a/libxrdp/libxrdpinc.h +++ b/libxrdp/libxrdpinc.h @@ -242,5 +242,8 @@ libxrdp_fastpath_send_surface(struct xrdp_session *session, int destLeft, int dst_Top, int destRight, int destBottom, int bpp, int codecID, int width, int height); +int EXPORT_CC +libxrdp_fastpath_send_frame_marker(struct xrdp_session *session, + int frame_action, int frame_id); #endif diff --git a/libxrdp/xrdp_caps.c b/libxrdp/xrdp_caps.c index a5883a01..98ab03fa 100644 --- a/libxrdp/xrdp_caps.c +++ b/libxrdp/xrdp_caps.c @@ -486,6 +486,15 @@ xrdp_caps_process_codecs(struct xrdp_rdp *self, struct stream *s, int len) } g_writeln(" jpeg quality set to %d", self->client_info.jpeg_prop[0]); } + else if (g_memcmp(codec_guid, XR_CODEC_GUID_H264, 16) == 0) + { + g_writeln("xrdp_caps_process_codecs: h264 codec id %d prop len %d", + codec_id, codec_properties_length); + self->client_info.h264_codec_id = codec_id; + i1 = MIN(64, codec_properties_length); + g_memcpy(self->client_info.h264_prop, s->p, i1); + self->client_info.h264_prop_len = i1; + } else { g_writeln("xrdp_caps_process_codecs: unknown codec id %d", codec_id); @@ -509,6 +518,17 @@ xrdp_caps_process_multifragmetupdate(struct xrdp_rdp *self, struct stream *s, return 0; } + /*****************************************************************************/ +static int APP_CC +xrdp_caps_process_frame_ack(struct xrdp_rdp *self, struct stream *s, int len) +{ + g_writeln("xrdp_caps_process_frame_ack:"); + self->client_info.use_frame_acks = 1; + in_uint32_le(s, self->client_info.max_unacknowledged_frame_count); + g_writeln(" max_unacknowledged_frame_count %d", self->client_info.max_unacknowledged_frame_count); + return 0; +} + /*****************************************************************************/ int APP_CC xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) @@ -626,6 +646,9 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) case RDP_CAPSET_BMPCODECS: /* 0x1d(29) */ xrdp_caps_process_codecs(self, s, len); break; + case 0x001E: /* CAPSSETTYPE_FRAME_ACKNOWLEDGE */ + xrdp_caps_process_frame_ack(self, s, len); + break; default: g_writeln("unknown in xrdp_caps_process_confirm_active %d", type); break; @@ -880,6 +903,12 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) out_uint32_le(s, 3 * 1024 * 1024); /* 3MB */ } + /* frame acks */ + caps_count++; + out_uint16_le(s, 0x001E); /* CAPSETTYPE_FRAME_ACKNOWLEDGE */ + out_uint16_le(s, 8); + out_uint32_le(s, 2); /* 2 frames in flight */ + out_uint8s(s, 4); /* pad */ s_mark_end(s); diff --git a/libxrdp/xrdp_fastpath.c b/libxrdp/xrdp_fastpath.c index 6a4eb78e..5bf63b29 100644 --- a/libxrdp/xrdp_fastpath.c +++ b/libxrdp/xrdp_fastpath.c @@ -112,18 +112,6 @@ xrdp_fastpath_init(struct xrdp_fastpath *self, struct stream *s) return 0; } -/*****************************************************************************/ -/* no fragmenation */ -int APP_CC -xrdp_fastpath_send(struct xrdp_fastpath *self, struct stream *s) -{ - if (trans_force_write_s(self->trans, s) != 0) - { - return 1; - } - return 0; -} - /*****************************************************************************/ static int APP_CC xrdp_fastpath_session_callback(struct xrdp_fastpath *self, int msg, @@ -144,6 +132,19 @@ xrdp_fastpath_session_callback(struct xrdp_fastpath *self, int msg, return 0; } +/*****************************************************************************/ +/* no fragmenation */ +int APP_CC +xrdp_fastpath_send(struct xrdp_fastpath *self, struct stream *s) +{ + if (trans_force_write_s(self->trans, s) != 0) + { + return 1; + } + xrdp_fastpath_session_callback(self, 0x5556, 0, 0, 0, 0); + return 0; +} + /*****************************************************************************/ /* FASTPATH_INPUT_EVENT_SCANCODE */ static int APP_CC diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index 34842533..72562022 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -1106,6 +1106,24 @@ xrdp_rdp_send_disconnect_reason(struct xrdp_rdp *self, int reason) } #endif +/*****************************************************************************/ +static int APP_CC +xrdp_rdp_process_frame_ack(struct xrdp_rdp *self, struct stream *s) +{ + int frame_id; + + //g_writeln("xrdp_rdp_process_frame_ack:"); + in_uint32_le(s, frame_id); + //g_writeln(" frame_id %d", frame_id); + if (self->session->callback != 0) + { + /* call to xrdp_wm.c : callback */ + self->session->callback(self->session->id, 0x5557, frame_id, 0, + 0, 0); + } + return 0; +} + /*****************************************************************************/ /* RDP_PDU_DATA */ int APP_CC @@ -1155,6 +1173,9 @@ xrdp_rdp_process_data(struct xrdp_rdp *self, struct stream *s) case RDP_DATA_PDU_FONT2: /* 39(0x27) */ xrdp_rdp_process_data_font(self, s); break; + case 56: /* PDUTYPE2_FRAME_ACKNOWLEDGE 0x38 */ + xrdp_rdp_process_frame_ack(self, s); + break; default: g_writeln("unknown in xrdp_rdp_process_data %d", data_type); break; diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h index 67488a60..b23cdaf0 100644 --- a/xrdp/xrdp.h +++ b/xrdp/xrdp.h @@ -378,6 +378,8 @@ xrdp_mm_get_wait_objs(struct xrdp_mm* self, tbus* read_objs, int* rcount, tbus* write_objs, int* wcount, int* timeout); int APP_CC +xrdp_mm_check_chan(struct xrdp_mm *self); +int APP_CC xrdp_mm_check_wait_objs(struct xrdp_mm* self); int DEFAULT_CC server_begin_update(struct xrdp_mod* mod); diff --git a/xrdp/xrdp_encoder.c b/xrdp/xrdp_encoder.c index 78d1b52e..2b96d803 100644 --- a/xrdp/xrdp_encoder.c +++ b/xrdp/xrdp_encoder.c @@ -39,30 +39,76 @@ } \ while (0) -#define JPG_CODEC 0 -#define RFX_CODEC 1 - /*****************************************************************************/ static int -process_enc_jpg(struct xrdp_mm *self, XRDP_ENC_DATA *enc); +process_enc_jpg(struct xrdp_encoder *self, XRDP_ENC_DATA *enc); +static int +process_enc_rfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc); static int -process_enc_rfx(struct xrdp_mm *self, XRDP_ENC_DATA *enc); +process_enc_h264(struct xrdp_encoder *self, XRDP_ENC_DATA *enc); -/** - * Init encoder - * - * @return 0 on success, -1 on failure - *****************************************************************************/ -/* called from main thread */ -int APP_CC -init_xrdp_encoder(struct xrdp_mm *self) +/*****************************************************************************/ +struct xrdp_encoder *APP_CC +xrdp_encoder_create(struct xrdp_mm *mm) { + struct xrdp_encoder *self; char buf[1024]; int pid; - if (self == 0) + if (mm->wm->client_info->mcs_connection_type != 6) /* LAN */ + { + return 0; + } + + if (mm->wm->client_info->bpp < 24) { - return -1; + return 0; + } + + self = (struct xrdp_encoder *)g_malloc(sizeof(struct xrdp_encoder), 1); + self->mm = mm; + + if (mm->wm->client_info->jpeg_codec_id != 0) + { + LLOGLN(0, ("xrdp_encoder_create: starting jpeg codec session")); + self->codec_id = mm->wm->client_info->jpeg_codec_id; + self->in_codec_mode = 1; + self->codec_quality = mm->wm->client_info->jpeg_prop[0]; + mm->wm->client_info->capture_code = 0; + mm->wm->client_info->capture_format = + /* XRDP_a8b8g8r8 */ + (32 << 24) | (3 << 16) | (8 << 12) | (8 << 8) | (8 << 4) | 8; + self->process_enc = process_enc_jpg; + } + else if (mm->wm->client_info->rfx_codec_id != 0) + { + LLOGLN(0, ("xrdp_encoder_create: starting rfx codec session")); + self->codec_id = mm->wm->client_info->rfx_codec_id; + self->in_codec_mode = 1; + mm->wm->client_info->capture_code = 2; + self->process_enc = process_enc_rfx; +#ifdef XRDP_RFXCODEC + self->codec_handle = + rfxcodec_encode_create(mm->wm->screen->width, + mm->wm->screen->height, + RFX_FORMAT_YUV, 0); +#endif + } + else if (mm->wm->client_info->h264_codec_id != 0) + { + LLOGLN(0, ("xrdp_encoder_create: starting h264 codec session")); + self->codec_id = mm->wm->client_info->h264_codec_id; + self->in_codec_mode = 1; + mm->wm->client_info->capture_code = 3; + mm->wm->client_info->capture_format = + /* XRDP_nv12 */ + (12 << 24) | (64 << 16) | (0 << 12) | (0 << 8) | (0 << 4) | 0; + self->process_enc = process_enc_h264; + } + else + { + g_free(self); + return 0; } LLOGLN(0, ("init_xrdp_encoder: initing encoder codec_id %d", self->codec_id)); @@ -81,52 +127,25 @@ init_xrdp_encoder(struct xrdp_mm *self) g_snprintf(buf, 1024, "xrdp_%8.8x_encoder_term", pid); self->xrdp_encoder_term = g_create_wait_obj(buf); - switch (self->codec_id) - { - case 2: - self->process_enc = process_enc_jpg; - break; - case 3: - self->process_enc = process_enc_rfx; -#ifdef XRDP_RFXCODEC - self->codec_handle = - rfxcodec_encode_create(self->wm->screen->width, - self->wm->screen->height, - RFX_FORMAT_YUV, 0); - //RFX_FORMAT_BGRA, 0); -#endif - break; - default: - LLOGLN(0, ("init_xrdp_encoder: unknown codec_id %d", - self->codec_id)); - break; - - } - /* create thread to process messages */ tc_thread_create(proc_enc_msg, self); - return 0; + return self; } -/** - * Deinit xrdp encoder - *****************************************************************************/ -/* called from main thread */ +/*****************************************************************************/ void APP_CC -deinit_xrdp_encoder(struct xrdp_mm *self) +xrdp_encoder_delete(struct xrdp_encoder *self) { XRDP_ENC_DATA *enc; XRDP_ENC_DATA_DONE *enc_done; - FIFO *fifo; - - LLOGLN(0, ("deinit_xrdp_encoder: deiniting encoder")); + FIFO *fifo; + LLOGLN(0, ("xrdp_encoder_delete:")); if (self == 0) { return; } - if (self->in_codec_mode == 0) { return; @@ -135,12 +154,7 @@ deinit_xrdp_encoder(struct xrdp_mm *self) g_set_wait_obj(self->xrdp_encoder_term); g_sleep(1000); - if (self->codec_id == 3) - { -#ifdef XRDP_RFXCODEC - rfxcodec_encode_destroy(self->codec_handle); -#endif - } + /* todo delete specific encoder */ /* destroy wait objects used for signalling */ g_delete_wait_obj(self->xrdp_encoder_event_to_proc); @@ -162,7 +176,6 @@ deinit_xrdp_encoder(struct xrdp_mm *self) g_free(enc->crects); g_free(enc); } - fifo_delete(fifo); } @@ -173,7 +186,7 @@ deinit_xrdp_encoder(struct xrdp_mm *self) while (!fifo_is_empty(fifo)) { enc_done = fifo_remove_item(fifo); - if (enc == 0) + if (enc_done == 0) { continue; } @@ -182,27 +195,28 @@ deinit_xrdp_encoder(struct xrdp_mm *self) } fifo_delete(fifo); } + g_free(self); } /*****************************************************************************/ /* called from encoder thread */ static int -process_enc_jpg(struct xrdp_mm *self, XRDP_ENC_DATA *enc) +process_enc_jpg(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) { - int index; - int x; - int y; - int cx; - int cy; - int quality; - int error; - int out_data_bytes; - int count; - char *out_data; - XRDP_ENC_DATA_DONE *enc_done; - FIFO *fifo_processed; - tbus mutex; - tbus event_processed; + int index; + int x; + int y; + int cx; + int cy; + int quality; + int error; + int out_data_bytes; + int count; + char *out_data; + XRDP_ENC_DATA_DONE *enc_done; + FIFO *fifo_processed; + tbus mutex; + tbus event_processed; LLOGLN(10, ("process_enc_jpg:")); quality = self->codec_quality; @@ -236,9 +250,10 @@ process_enc_jpg(struct xrdp_mm *self, XRDP_ENC_DATA *enc) LLOGLN(0, ("process_enc_jpg: error 3")); return 1; } + out_data[256] = 0; /* header bytes */ out_data[257] = 0; - error = libxrdp_codec_jpeg_compress(self->wm->session, 0, enc->data, + error = libxrdp_codec_jpeg_compress(self->mm->wm->session, 0, enc->data, enc->width, enc->height, enc->width * 4, x, y, cx, cy, quality, @@ -278,7 +293,7 @@ process_enc_jpg(struct xrdp_mm *self, XRDP_ENC_DATA *enc) /*****************************************************************************/ /* called from encoder thread */ static int -process_enc_rfx(struct xrdp_mm *self, XRDP_ENC_DATA *enc) +process_enc_rfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) { int index; int x; @@ -364,8 +379,8 @@ process_enc_rfx(struct xrdp_mm *self, XRDP_ENC_DATA *enc) enc_done->comp_pad_data = out_data; enc_done->enc = enc; enc_done->last = 1; - enc_done->cx = self->wm->screen->width; - enc_done->cy = self->wm->screen->height; + enc_done->cx = self->mm->wm->screen->width; + enc_done->cy = self->mm->wm->screen->height; /* done with msg */ /* inform main thread done */ @@ -383,36 +398,45 @@ process_enc_rfx(struct xrdp_mm *self, XRDP_ENC_DATA *enc) /*****************************************************************************/ /* called from encoder thread */ static int -process_enc_rfx(struct xrdp_mm *self, XRDP_ENC_DATA *enc) +process_enc_rfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) { return 0; } #endif +/*****************************************************************************/ +/* called from encoder thread */ +static int +process_enc_h264(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) +{ + LLOGLN(0, ("process_enc_x264:")); + return 0; +} + /** * Encoder thread main loop *****************************************************************************/ THREAD_RV THREAD_CC proc_enc_msg(void *arg) { - XRDP_ENC_DATA *enc; - FIFO *fifo_to_proc; - tbus mutex; - tbus event_to_proc; - tbus term_obj; - tbus lterm_obj; - int robjs_count; - int wobjs_count; - int cont; - int timeout; - tbus robjs[32]; - tbus wobjs[32]; - struct xrdp_mm *self; + XRDP_ENC_DATA *enc; + FIFO *fifo_to_proc; + tbus mutex; + tbus event_to_proc; + tbus term_obj; + tbus lterm_obj; + int robjs_count; + int wobjs_count; + int cont; + int timeout; + tbus robjs[32]; + tbus wobjs[32]; + struct xrdp_encoder *self; LLOGLN(0, ("proc_enc_msg: thread is running")); - self = (struct xrdp_mm *) arg; + self = (struct xrdp_encoder *) arg; if (self == 0) { LLOGLN(0, ("proc_enc_msg: self nil")); diff --git a/xrdp/xrdp_encoder.h b/xrdp/xrdp_encoder.h index 1d525f12..f138d749 100644 --- a/xrdp/xrdp_encoder.h +++ b/xrdp/xrdp_encoder.h @@ -3,13 +3,67 @@ #define _XRDP_ENCODER_H #include "arch.h" +#include "fifo.h" -struct xrdp_mm; +struct xrdp_enc_data; -int APP_CC -init_xrdp_encoder(struct xrdp_mm *self); +/* for codec mode operations */ +struct xrdp_encoder +{ + struct xrdp_mm *mm; + int in_codec_mode; + int codec_id; + int codec_quality; + tbus xrdp_encoder_event_to_proc; + tbus xrdp_encoder_event_processed; + tbus xrdp_encoder_term; + FIFO *fifo_to_proc; + FIFO *fifo_processed; + tbus mutex; + int (*process_enc)(struct xrdp_encoder *self, struct xrdp_enc_data *enc); + void *codec_handle; + int frame_id_client; /* last frame id received from client */ + int frame_id_server; /* last frame id received from Xorg */ + int frame_id_server_sent; +}; + +/* used when scheduling tasks in xrdp_encoder.c */ +struct xrdp_enc_data +{ + struct xrdp_mod *mod; + int num_drects; + short *drects; /* 4 * num_drects */ + int num_crects; + short *crects; /* 4 * num_crects */ + char *data; + int width; + int height; + int flags; + int frame_id; +}; + +typedef struct xrdp_enc_data XRDP_ENC_DATA; + +/* used when scheduling tasks from xrdp_encoder.c */ +struct xrdp_enc_data_done +{ + int comp_bytes; + int pad_bytes; + char *comp_pad_data; + struct xrdp_enc_data *enc; + int last; /* true is this is last message for enc */ + int x; + int y; + int cx; + int cy; +}; + +typedef struct xrdp_enc_data_done XRDP_ENC_DATA_DONE; + +struct xrdp_encoder *APP_CC +xrdp_encoder_create(struct xrdp_mm *mm); void APP_CC -deinit_xrdp_encoder(struct xrdp_mm *self); +xrdp_encoder_delete(struct xrdp_encoder *self); THREAD_RV THREAD_CC proc_enc_msg(void *arg); diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index 76957ad6..8d67016b 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -58,46 +58,16 @@ xrdp_mm_create(struct xrdp_wm *owner) self->login_values->auto_free = 1; LLOGLN(0, ("xrdp_mm_create: bpp %d mcs_connection_type %d " - "jpeg_codec_id %d v3_codec_id %d rfx_codec_id %d", + "jpeg_codec_id %d v3_codec_id %d rfx_codec_id %d " + "h264_codec_id %d", self->wm->client_info->bpp, self->wm->client_info->mcs_connection_type, self->wm->client_info->jpeg_codec_id, self->wm->client_info->v3_codec_id, - self->wm->client_info->rfx_codec_id)); - /* go into jpeg codec mode if jpeg set, lan set */ - if (self->wm->client_info->mcs_connection_type == 6) /* LAN */ - { - if (self->wm->client_info->jpeg_codec_id == 2) /* JPEG */ - { - if (self->wm->client_info->bpp > 16) - { - LLOGLN(0, ("xrdp_mm_create: starting jpeg codec session")); - self->codec_id = 2; - self->in_codec_mode = 1; - self->codec_quality = self->wm->client_info->jpeg_prop[0]; - self->wm->client_info->capture_code = 0; - self->wm->client_info->capture_format = - /* PIXMAN_a8b8g8r8 */ - (32 << 24) | (3 << 16) | (8 << 12) | (8 << 8) | (8 << 4) | 8; - } - } - else if (self->wm->client_info->rfx_codec_id == 3) /* RFX */ - { - if (self->wm->client_info->bpp > 16) - { - LLOGLN(0, ("xrdp_mm_create: starting rfx codec session")); - self->codec_id = 3; - self->in_codec_mode = 1; - self->wm->client_info->capture_code = 2; - } - } - } + self->wm->client_info->rfx_codec_id, + self->wm->client_info->h264_codec_id)); - if (self->in_codec_mode) - { - /* setup thread to handle codec mode messages */ - init_xrdp_encoder(self); - } + self->encoder = xrdp_encoder_create(self); return self; } @@ -174,7 +144,7 @@ xrdp_mm_delete(struct xrdp_mm *self) xrdp_mm_module_cleanup(self); /* shutdown thread */ - deinit_xrdp_encoder(self); + xrdp_encoder_delete(self->encoder); trans_delete(self->sesman_trans); self->sesman_trans = 0; @@ -1956,9 +1926,9 @@ xrdp_mm_get_wait_objs(struct xrdp_mm *self, } } - if (self->in_codec_mode) + if (self->encoder != 0) { - read_objs[(*rcount)++] = self->xrdp_encoder_event_processed; + read_objs[(*rcount)++] = self->encoder->xrdp_encoder_event_processed; } return rv; @@ -2019,6 +1989,28 @@ xrdp_mm_dump_jpeg(struct xrdp_mm *self, XRDP_ENC_DATA_DONE *enc_done) #endif +/*****************************************************************************/ +int APP_CC +xrdp_mm_check_chan(struct xrdp_mm *self) +{ + //g_writeln("xrdp_mm_check_chan:"); + if ((self->chan_trans != 0) && self->chan_trans_up) + { + if (trans_check_wait_objs(self->chan_trans) != 0) + { + self->delete_chan_trans = 1; + } + } + if (self->delete_chan_trans) + { + trans_delete(self->chan_trans); + self->chan_trans = 0; + self->chan_trans_up = 0; + self->delete_chan_trans = 0; + } + return 0; +} + /*****************************************************************************/ int APP_CC xrdp_mm_check_wait_objs(struct xrdp_mm *self) @@ -2029,6 +2021,8 @@ xrdp_mm_check_wait_objs(struct xrdp_mm *self) int y; int cx; int cy; + int use_frame_acks; + int ex; if (self == 0) { @@ -2077,15 +2071,18 @@ xrdp_mm_check_wait_objs(struct xrdp_mm *self) self->delete_chan_trans = 0; } - if (self->in_codec_mode) + if (self->encoder != 0) { - if (g_is_wait_obj_set(self->xrdp_encoder_event_processed)) + + use_frame_acks = self->wm->client_info->use_frame_acks; + + if (g_is_wait_obj_set(self->encoder->xrdp_encoder_event_processed)) { - g_reset_wait_obj(self->xrdp_encoder_event_processed); - tc_mutex_lock(self->mutex); + g_reset_wait_obj(self->encoder->xrdp_encoder_event_processed); + tc_mutex_lock(self->encoder->mutex); enc_done = (XRDP_ENC_DATA_DONE*) - fifo_remove_item(self->fifo_processed); - tc_mutex_unlock(self->mutex); + fifo_remove_item(self->encoder->fifo_processed); + tc_mutex_unlock(self->encoder->mutex); while (enc_done != 0) { /* do something with msg */ @@ -2103,36 +2100,85 @@ xrdp_mm_check_wait_objs(struct xrdp_mm *self) if (enc_done->comp_bytes > 0) { + libxrdp_fastpath_send_frame_marker(self->wm->session, 0, + enc_done->enc->frame_id); libxrdp_fastpath_send_surface(self->wm->session, enc_done->comp_pad_data, enc_done->pad_bytes, enc_done->comp_bytes, x, y, x + cx, y + cy, - 32, self->codec_id, cx, cy); + 32, self->encoder->codec_id, cx, cy); + libxrdp_fastpath_send_frame_marker(self->wm->session, 1, + enc_done->enc->frame_id); } /* free enc_done */ if (enc_done->last) { LLOGLN(10, ("xrdp_mm_check_wait_objs: last set")); - self->mod->mod_frame_ack(self->mod, - enc_done->enc->flags, enc_done->enc->frame_id); + if (use_frame_acks == 0) + { + self->mod->mod_frame_ack(self->mod, + enc_done->enc->flags, + enc_done->enc->frame_id); + } + else + { +#if 1 + ex = self->wm->client_info->max_unacknowledged_frame_count; + if (self->encoder->frame_id_client + ex > self->encoder->frame_id_server) + { + if (self->encoder->frame_id_server > self->encoder->frame_id_server_sent) + { + LLOGLN(10, ("xrdp_mm_check_wait_objs: 1 -- %d", self->encoder->frame_id_server)); + self->encoder->frame_id_server_sent = self->encoder->frame_id_server; + self->mod->mod_frame_ack(self->mod, 0, self->encoder->frame_id_server); + } + } +#endif + } g_free(enc_done->enc->drects); g_free(enc_done->enc->crects); g_free(enc_done->enc); } g_free(enc_done->comp_pad_data); g_free(enc_done); - tc_mutex_lock(self->mutex); + tc_mutex_lock(self->encoder->mutex); enc_done = (XRDP_ENC_DATA_DONE*) - fifo_remove_item(self->fifo_processed); - tc_mutex_unlock(self->mutex); + fifo_remove_item(self->encoder->fifo_processed); + tc_mutex_unlock(self->encoder->mutex); } } } return rv; } +/*****************************************************************************/ +/* frame ack from client */ +int APP_CC +xrdp_mm_frame_ack(struct xrdp_mm *self, int frame_id) +{ + int ex; + + LLOGLN(0, ("xrdp_mm_frame_ack:")); + self->encoder->frame_id_client = frame_id; + if (self->wm->client_info->use_frame_acks == 0) + { + return 1; + } + ex = self->wm->client_info->max_unacknowledged_frame_count; + if (self->encoder->frame_id_client + ex > self->encoder->frame_id_server) + { + if (self->encoder->frame_id_server > self->encoder->frame_id_server_sent) + { + LLOGLN(10, ("xrdp_mm_frame_ack: frame_id_server %d", self->encoder->frame_id_server)); + self->encoder->frame_id_server_sent = self->encoder->frame_id_server; + self->mod->mod_frame_ack(self->mod, 0, self->encoder->frame_id_server); + } + } + return 0; +} + #if 0 /*****************************************************************************/ struct xrdp_painter *APP_CC @@ -2354,9 +2400,9 @@ server_paint_rects(struct xrdp_mod* mod, int num_drects, short *drects, mm = wm->mm; LLOGLN(10, ("server_paint_rects:")); - LLOGLN(10, ("server_paint_rects: %d", mm->in_codec_mode)); + LLOGLN(10, ("server_paint_rects: %p", mm->encoder)); - if (mm->in_codec_mode) + if (mm->encoder != 0) { /* copy formal params to XRDP_ENC_DATA */ enc_data = (XRDP_ENC_DATA *) g_malloc(sizeof(XRDP_ENC_DATA), 1); @@ -2393,18 +2439,19 @@ server_paint_rects(struct xrdp_mod* mod, int num_drects, short *drects, enc_data->height = height; enc_data->flags = flags; enc_data->frame_id = frame_id; + mm->encoder->frame_id_server = frame_id; if (width == 0 || height == 0) { LLOGLN(10, ("server_paint_rects: error")); } /* insert into fifo for encoder thread to process */ - tc_mutex_lock(mm->mutex); - fifo_add_item(mm->fifo_to_proc, (void *) enc_data); - tc_mutex_unlock(mm->mutex); + tc_mutex_lock(mm->encoder->mutex); + fifo_add_item(mm->encoder->fifo_to_proc, (void *) enc_data); + tc_mutex_unlock(mm->encoder->mutex); /* signal xrdp_encoder thread */ - g_set_wait_obj(mm->xrdp_encoder_event_to_proc); + g_set_wait_obj(mm->encoder->xrdp_encoder_event_to_proc); return 0; } diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index 29aaac84..21d00e9a 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -292,19 +292,7 @@ struct xrdp_mm int chan_trans_up; /* true once connected to chansrv */ int delete_chan_trans; /* boolean set when done with channel connection */ int usechansrv; /* true if chansrvport is set in xrdp.ini or using sesman */ - - /* for codec mode operations */ - int in_codec_mode; - int codec_id; - int codec_quality; - tbus xrdp_encoder_event_to_proc; - tbus xrdp_encoder_event_processed; - tbus xrdp_encoder_term; - FIFO *fifo_to_proc; - FIFO *fifo_processed; - tbus mutex; - int (*process_enc)(struct xrdp_mm *self, struct xrdp_enc_data *enc); - void *codec_handle; + struct xrdp_encoder *encoder; }; struct xrdp_key_info @@ -624,39 +612,4 @@ struct xrdp_config struct xrdp_cfg_channels cfg_channels; }; -/* used when scheduling tasks in xrdp_encoder.c */ -struct xrdp_enc_data -{ - struct xrdp_mod *mod; - int num_drects; - short *drects; /* 4 * num_drects */ - int num_crects; - short *crects; /* 4 * num_crects */ - char *data; - int width; - int height; - int flags; - int frame_id; -}; - -typedef struct xrdp_enc_data XRDP_ENC_DATA; - -/* used when scheduling tasks from xrdp_encoder.c */ -struct xrdp_enc_data_done -{ - int comp_bytes; - int pad_bytes; - char *comp_pad_data; - struct xrdp_enc_data *enc; - int last; /* true is this is last message for enc */ - int x; - int y; - int cx; - int cy; -}; - -typedef struct xrdp_enc_data_done XRDP_ENC_DATA_DONE; - - - #endif diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c index 591c8a51..e3af0f05 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -1733,8 +1733,14 @@ callback(long id, int msg, long param1, long param2, long param3, long param4) pass it to module if there is one */ rv = xrdp_wm_process_channel_data(wm, param1, param2, param3, param4); break; + case 0x5556: + rv = xrdp_mm_check_chan(wm->mm); + break; + case 0x5557: + //g_writeln("callback: frame ack %d", param1); + xrdp_mm_frame_ack(wm->mm, param1); + break; } - return rv; }