Created
October 4, 2024 23:19
-
-
Save nedix/b1905c60743dddd52aa455e9fc3f898e to your computer and use it in GitHub Desktop.
Conflicts xrdp_encoder.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 95183e139112cf958a2cabd4590dda1df94b8939 Mon Sep 17 00:00:00 2001 | |
From: NEDIX <[email protected]> | |
Date: Sat, 5 Oct 2024 01:17:04 +0200 | |
Subject: [PATCH] Conflicts xrdp_encoder.c | |
--- | |
xrdp/xrdp_encoder.c | 1266 ++++++++++++++++++------------------------- | |
1 file changed, 538 insertions(+), 728 deletions(-) | |
diff --git xrdp/xrdp_encoder.c xrdp/xrdp_encoder.c | |
index f96515bd..73bd330b 100644 | |
--- xrdp/xrdp_encoder.c | |
+++ xrdp/xrdp_encoder.c | |
@@ -168,63 +168,78 @@ xrdp_encoder_create(struct xrdp_mm *mm) | |
return NULL; | |
} | |
self->mm = mm; | |
- | |
- if (mm->egfx_flags & 1) | |
+ self->process_enc = process_enc_egfx; | |
+ if (client_info->jpeg_codec_id != 0) | |
+ { | |
+ LOG(LOG_LEVEL_INFO, "xrdp_encoder_create: starting jpeg codec session"); | |
+ self->codec_id = client_info->jpeg_codec_id; | |
+ self->in_codec_mode = 1; | |
+ self->codec_quality = client_info->jpeg_prop[0]; | |
+ client_info->capture_code = CC_SIMPLE; | |
+ client_info->capture_format = XRDP_a8b8g8r8; | |
+ self->process_enc = process_enc_jpg; | |
+ } | |
+#ifdef XRDP_X264 | |
+ else if (mm->egfx_flags & XRDP_EGFX_H264) | |
{ | |
LOG(LOG_LEVEL_INFO, | |
"xrdp_encoder_create: starting h264 codec session gfx"); | |
self->in_codec_mode = 1; | |
- client_info->capture_code = 3; | |
- client_info->capture_format = | |
-#if AVC444 | |
- /* XRDP_yuv444_709fr */ | |
- (32 << 24) | (67 << 16) | (0 << 12) | (0 << 8) | (0 << 4) | 0; | |
-#else | |
- /* XRDP_nv12_709fr */ | |
- (12 << 24) | (66 << 16) | (0 << 12) | (0 << 8) | (0 << 4) | 0; | |
-#endif | |
- self->process_enc = process_enc_h264; | |
+ client_info->capture_code = CC_GFX_A2; | |
+ client_info->capture_format = XRDP_nv12_709fr; | |
self->gfx = 1; | |
-#if defined(XRDP_VANILLA_NVIDIA_CODEC) | |
- self->codec_handle = xrdp_encoder_nvenc_create(); | |
-#elif defined(XRDP_X264) | |
- self->codec_handle = xrdp_encoder_x264_create(); | |
-#elif defined(XRDP_OPENH264) | |
- self->codec_handle = xrdp_encoder_openh264_create(); | |
-#endif | |
} | |
+ else if (client_info->h264_codec_id != 0) | |
+ { | |
+ LOG(LOG_LEVEL_INFO, "xrdp_encoder_create: starting h264 codec session"); | |
+ self->codec_id = client_info->h264_codec_id; | |
+ self->in_codec_mode = 1; | |
+ client_info->capture_code = CC_SUF_A2; | |
+ client_info->capture_format = XRDP_nv12; | |
+ self->process_enc = process_enc_h264; | |
+ } | |
+#endif | |
#ifdef XRDP_RFXCODEC | |
- else if (mm->egfx_flags & 2) | |
+ else if (mm->egfx_flags & XRDP_EGFX_RFX_PRO) | |
{ | |
LOG(LOG_LEVEL_INFO, | |
"xrdp_encoder_create: starting gfx rfx pro codec session"); | |
self->in_codec_mode = 1; | |
- client_info->capture_code = 2; | |
- self->process_enc = process_enc_rfx; | |
+ client_info->capture_code = CC_GFX_PRO; | |
self->gfx = 1; | |
- self->quants = (const char *) g_rfx_quantization_values; | |
self->num_quants = 2; | |
self->quant_idx_y = 0; | |
self->quant_idx_u = 1; | |
self->quant_idx_v = 1; | |
- self->codec_handle = rfxcodec_encode_create( | |
- mm->wm->screen->width, | |
- mm->wm->screen->height, | |
- RFX_FORMAT_YUV, | |
- RFX_FLAGS_RLGR1 | RFX_FLAGS_PRO1); | |
- } | |
+ switch (client_info->mcs_connection_type) | |
+ { | |
+ case CONNECTION_TYPE_MODEM: | |
+ case CONNECTION_TYPE_BROADBAND_LOW: | |
+ case CONNECTION_TYPE_SATELLITE: | |
+ self->quants = (const char *) g_rfx_quantization_values_ulq; | |
+ break; | |
+ case CONNECTION_TYPE_BROADBAND_HIGH: | |
+ case CONNECTION_TYPE_WAN: | |
+ self->quants = (const char *) g_rfx_quantization_values_lq; | |
+ break; | |
+ case CONNECTION_TYPE_LAN: | |
+ case CONNECTION_TYPE_AUTODETECT: /* not implemented yet */ | |
+ default: | |
+ self->quants = (const char *) g_rfx_quantization_values_std; | |
+ | |
+ } | |
+ } | |
else if (client_info->rfx_codec_id != 0) | |
{ | |
- LOG_DEVEL(LOG_LEVEL_INFO, | |
- "xrdp_encoder_create: starting rfx codec session"); | |
+ LOG(LOG_LEVEL_INFO, "xrdp_encoder_create: starting rfx codec session"); | |
self->codec_id = client_info->rfx_codec_id; | |
self->in_codec_mode = 1; | |
- client_info->capture_code = 2; | |
+ client_info->capture_code = CC_SUF_RFX; | |
self->process_enc = process_enc_rfx; | |
- self->codec_handle = rfxcodec_encode_create(mm->wm->screen->width, | |
- mm->wm->screen->height, | |
- RFX_FORMAT_YUV, 0); | |
+ self->codec_handle_rfx = rfxcodec_encode_create(mm->wm->screen->width, | |
+ mm->wm->screen->height, | |
+ RFX_FORMAT_YUV, 0); | |
} | |
#endif | |
else if (client_info->jpeg_codec_id != 0) | |
@@ -349,9 +364,9 @@ xrdp_encoder_create(struct xrdp_mm *mm) | |
void | |
xrdp_encoder_delete(struct xrdp_encoder *self) | |
{ | |
- XRDP_ENC_DATA *enc; | |
- XRDP_ENC_DATA_DONE *enc_done; | |
- FIFO *fifo; | |
+ int index; | |
+ | |
+ (void)index; | |
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_encoder_delete:"); | |
if (self == 0) | |
@@ -363,76 +378,50 @@ xrdp_encoder_delete(struct xrdp_encoder *self) | |
return; | |
} | |
/* tell worker thread to shut down */ | |
- g_set_wait_obj(self->xrdp_encoder_term); | |
- g_sleep(1000); | |
- | |
- /* todo delete specific encoder */ | |
- | |
- if (self->process_enc == process_enc_jpg) | |
+ g_set_wait_obj(self->xrdp_encoder_term_request); | |
+ g_obj_wait(&self->xrdp_encoder_term_done, 1, NULL, 0, 5000); | |
+ if (!g_is_wait_obj_set(self->xrdp_encoder_term_done)) | |
{ | |
+ LOG(LOG_LEVEL_WARNING, "Encoder failed to shut down cleanly"); | |
} | |
+ | |
#ifdef XRDP_RFXCODEC | |
- else if (self->process_enc == process_enc_rfx) | |
+ for (index = 0; index < 16; index++) | |
{ | |
- rfxcodec_encode_destroy(self->codec_handle); | |
+ if (self->codec_handle_prfx_gfx[index] != NULL) | |
+ { | |
+ rfxcodec_encode_destroy(self->codec_handle_prfx_gfx[index]); | |
+ } | |
} | |
-#endif | |
-#if defined(XRDP_VANILLA_NVIDIA_CODEC) | |
- else if (self->process_enc == process_enc_h264) | |
+ if (self->codec_handle_rfx != NULL) | |
{ | |
- xrdp_encoder_nvenc_delete(self->codec_handle); | |
+ rfxcodec_encode_destroy(self->codec_handle_rfx); | |
} | |
-#elif defined(XRDP_X264) | |
- else if (self->process_enc == process_enc_h264) | |
+#endif | |
+ | |
+#if defined(XRDP_X264) | |
+ for (index = 0; index < 16; index++) | |
{ | |
- xrdp_encoder_x264_delete(self->codec_handle); | |
+ if (self->codec_handle_h264_gfx[index] != NULL) | |
+ { | |
+ xrdp_encoder_x264_delete(self->codec_handle_h264_gfx[index]); | |
+ } | |
} | |
-#elif defined(XRDP_OPENH264) | |
- else if (self->process_enc == process_enc_h264) | |
+ if (self->codec_handle_h264 != NULL) | |
{ | |
- xrdp_encoder_openh264_delete(self->codec_handle); | |
+ xrdp_encoder_x264_delete(self->codec_handle_h264); | |
} | |
#endif | |
+ | |
/* destroy wait objects used for signalling */ | |
g_delete_wait_obj(self->xrdp_encoder_event_to_proc); | |
g_delete_wait_obj(self->xrdp_encoder_event_processed); | |
- g_delete_wait_obj(self->xrdp_encoder_term); | |
+ g_delete_wait_obj(self->xrdp_encoder_term_request); | |
+ g_delete_wait_obj(self->xrdp_encoder_term_done); | |
- /* cleanup fifo_to_proc */ | |
- fifo = self->fifo_to_proc; | |
- if (fifo) | |
- { | |
- while (!fifo_is_empty(fifo)) | |
- { | |
- enc = (XRDP_ENC_DATA *) fifo_remove_item(fifo); | |
- if (enc == NULL) | |
- { | |
- continue; | |
- } | |
- g_free(enc->drects); | |
- g_free(enc->crects); | |
- g_free(enc); | |
- } | |
- fifo_delete(fifo); | |
- } | |
- | |
- /* cleanup fifo_processed */ | |
- fifo = self->fifo_processed; | |
- if (fifo) | |
- { | |
- while (!fifo_is_empty(fifo)) | |
- { | |
- enc_done = (XRDP_ENC_DATA_DONE *) fifo_remove_item(fifo); | |
- if (enc_done == NULL) | |
- { | |
- continue; | |
- } | |
- g_free(enc_done->comp_pad_data1); | |
- g_free(enc_done->comp_pad_data2); | |
- g_free(enc_done); | |
- } | |
- fifo_delete(fifo); | |
- } | |
+ /* cleanup fifos */ | |
+ fifo_delete(self->fifo_to_proc, NULL); | |
+ fifo_delete(self->fifo_processed, NULL); | |
tc_mutex_delete(self->mutex); | |
g_free(self); | |
} | |
@@ -453,7 +442,7 @@ process_enc_jpg(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) | |
int count; | |
char *out_data; | |
XRDP_ENC_DATA_DONE *enc_done; | |
- FIFO *fifo_processed; | |
+ struct fifo *fifo_processed; | |
tbus mutex; | |
tbus event_processed; | |
@@ -462,29 +451,32 @@ process_enc_jpg(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) | |
fifo_processed = self->fifo_processed; | |
mutex = self->mutex; | |
event_processed = self->xrdp_encoder_event_processed; | |
- count = enc->num_crects; | |
+ count = enc->u.sc.num_crects; | |
for (index = 0; index < count; index++) | |
{ | |
- x = enc->crects[index * 4 + 0]; | |
- y = enc->crects[index * 4 + 1]; | |
- cx = enc->crects[index * 4 + 2]; | |
- cy = enc->crects[index * 4 + 3]; | |
+ x = enc->u.sc.crects[index * 4 + 0]; | |
+ y = enc->u.sc.crects[index * 4 + 1]; | |
+ cx = enc->u.sc.crects[index * 4 + 2]; | |
+ cy = enc->u.sc.crects[index * 4 + 3]; | |
if (cx < 1 || cy < 1) | |
{ | |
LOG_DEVEL(LOG_LEVEL_WARNING, "process_enc_jpg: error 1"); | |
continue; | |
} | |
- LOG_DEVEL(LOG_LEVEL_DEBUG, "process_enc_jpg: x %d y %d cx %d cy %d", x, y, cx, cy); | |
+ LOG_DEVEL(LOG_LEVEL_DEBUG, "process_enc_jpg: x %d y %d cx %d cy %d", | |
+ x, y, cx, cy); | |
out_data_bytes = MAX((cx + 4) * cy * 4, 8192); | |
- if ((out_data_bytes < 1) || (out_data_bytes > 16 * 1024 * 1024)) | |
+ if ((out_data_bytes < 1) | |
+ || (out_data_bytes > OUT_DATA_BYTES_DEFAULT_SIZE)) | |
{ | |
LOG_DEVEL(LOG_LEVEL_ERROR, "process_enc_jpg: error 2"); | |
return 1; | |
} | |
- out_data = g_new(char, out_data_bytes + 256 + 2); | |
- if (out_data == NULL) | |
+ out_data = (char *) g_malloc(out_data_bytes | |
+ + XRDP_SURCMD_PREFIX_BYTES + 2, 0); | |
+ if (out_data == 0) | |
{ | |
LOG_DEVEL(LOG_LEVEL_ERROR, "process_enc_jpg: error 3"); | |
return 1; | |
@@ -492,33 +484,27 @@ process_enc_jpg(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) | |
out_data[256] = 0; /* header bytes */ | |
out_data[257] = 0; | |
- error = libxrdp_codec_jpeg_compress(self->mm->wm->session, 0, enc->data, | |
- enc->width, enc->height, | |
- enc->width * 4, x, y, cx, cy, | |
+ error = libxrdp_codec_jpeg_compress(self->mm->wm->session, 0, enc->u.sc.data, | |
+ enc->u.sc.width, enc->u.sc.height, | |
+ enc->u.sc.width * 4, x, y, cx, cy, | |
quality, | |
- out_data + 256 + 2, | |
+ out_data | |
+ + XRDP_SURCMD_PREFIX_BYTES + 2, | |
&out_data_bytes); | |
if (error < 0) | |
{ | |
- LOG_DEVEL(LOG_LEVEL_ERROR, | |
- "process_enc_jpg: jpeg error %d bytes %d", | |
- error, out_data_bytes); | |
+ LOG_DEVEL(LOG_LEVEL_ERROR, "process_enc_jpg: jpeg error %d " | |
+ "bytes %d", error, out_data_bytes); | |
g_free(out_data); | |
return 1; | |
} | |
LOG_DEVEL(LOG_LEVEL_WARNING, | |
"jpeg error %d bytes %d", error, out_data_bytes); | |
- enc_done = g_new0(XRDP_ENC_DATA_DONE, 1); | |
- if (enc_done == NULL) | |
- { | |
- LOG(LOG_LEVEL_INFO, "process_enc_jpg: error 3"); | |
- return 1; | |
- } | |
- | |
- enc_done->pad_bytes1 = 256; | |
- enc_done->comp_bytes1 = out_data_bytes + 2; | |
- enc_done->comp_pad_data1 = out_data; | |
- | |
+ enc_done = (XRDP_ENC_DATA_DONE *) | |
+ g_malloc(sizeof(XRDP_ENC_DATA_DONE), 1); | |
+ enc_done->comp_bytes = out_data_bytes + 2; | |
+ enc_done->pad_bytes = 256; | |
+ enc_done->comp_pad_data = out_data; | |
enc_done->enc = enc; | |
enc_done->last = index == (enc->u.sc.num_crects - 1); | |
enc_done->x = x; | |
@@ -624,15 +610,23 @@ process_enc_rfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) | |
} | |
out_data_bytes = self->max_compressed_bytes; | |
- tiles_written = rfxcodec_encode(self->codec_handle, | |
- out_data + XRDP_SURCMD_PREFIX_BYTES, | |
- &out_data_bytes, enc->data, | |
- enc->width, enc->height, | |
- enc->width * 4, | |
- rfxrects, enc->num_drects, | |
- tiles, enc->num_crects, | |
- self->quants, self->num_quants); | |
+ | |
+ encode_flags = 0; | |
+ if (((int)enc->flags & KEY_FRAME_REQUESTED) && encode_passes == 0) | |
+ { | |
+ encode_flags = RFX_FLAGS_PRO_KEY; | |
+ } | |
+ tiles_written = rfxcodec_encode_ex(self->codec_handle_rfx, | |
+ out_data + XRDP_SURCMD_PREFIX_BYTES, | |
+ &out_data_bytes, enc->u.sc.data, | |
+ enc->u.sc.width, enc->u.sc.height, | |
+ ((enc->u.sc.width + 63) & ~63) * 4, | |
+ rfxrects, enc->u.sc.num_drects, | |
+ tiles, enc->u.sc.num_crects, | |
+ self->quants, self->num_quants, | |
+ encode_flags); | |
} | |
+ ++encode_passes; | |
} | |
LOG_DEVEL(LOG_LEVEL_DEBUG, | |
@@ -680,687 +674,505 @@ process_enc_rfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) | |
/* signal completion for main thread */ | |
g_set_wait_obj(event_processed); | |
- } | |
- while (!finished); | |
- | |
return 0; | |
} | |
#endif | |
-#define SAVE_VIDEO 0 | |
- | |
-#if SAVE_VIDEO | |
-#include <sys/types.h> | |
-#include <sys/stat.h> | |
-#include <fcntl.h> | |
-#include <unistd.h> | |
+#if defined(XRDP_X264) | |
-static int n_save_data(const char *data, int data_size, int width, int height) | |
+/*****************************************************************************/ | |
+static int | |
+out_RFX_AVC420_METABLOCK(struct xrdp_egfx_rect *dst_rect, | |
+ struct stream *s, | |
+ struct xrdp_egfx_rect *rects, | |
+ int num_rects) | |
{ | |
- int fd; | |
- struct _header | |
- { | |
- char tag[4]; | |
- int width; | |
- int height; | |
- int bytes_follow; | |
- } header; | |
- | |
- fd = open("/home/christopher/video.bin", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); | |
- lseek(fd, 0, SEEK_END); | |
- header.tag[0] = 'B'; | |
- header.tag[1] = 'E'; | |
- header.tag[2] = 'E'; | |
- header.tag[3] = 'F'; | |
- header.width = width; | |
- header.height = height; | |
- header.bytes_follow = data_size; | |
- if (write(fd, &header, 16) != 16) | |
- { | |
- g_printf("save_data: write failed\n"); | |
- } | |
+ struct xrdp_region *reg; | |
+ struct xrdp_rect rect; | |
+ int index; | |
+ int count; | |
- if (write(fd, data, data_size) != data_size) | |
- { | |
- g_printf("save_data: write failed\n"); | |
- } | |
- close(fd); | |
+ /* RFX_AVC420_METABLOCK */ | |
+ s_push_layer(s, iso_hdr, 4); /* numRegionRects, set later */ | |
+ reg = xrdp_region_create(NULL); | |
+ if (reg == NULL) | |
+ { | |
+ return 1; | |
+ } | |
+ for (index = 0; index < num_rects; index++) | |
+ { | |
+ rect.left = MAX(0, rects[index].x1 - dst_rect->x1 - 1); | |
+ rect.top = MAX(0, rects[index].y1 - dst_rect->y1 - 1); | |
+ rect.right = MIN(dst_rect->x2 - dst_rect->x1, | |
+ rects[index].x2 - dst_rect->x1 + 1); | |
+ rect.bottom = MIN(dst_rect->y2 - dst_rect->y1, | |
+ rects[index].y2 - dst_rect->y1 + 1); | |
+ xrdp_region_add_rect(reg, &rect); | |
+ } | |
+ index = 0; | |
+ while (xrdp_region_get_rect(reg, index, &rect) == 0) | |
+ { | |
+ out_uint16_le(s, rect.left); | |
+ out_uint16_le(s, rect.top); | |
+ out_uint16_le(s, rect.right); | |
+ out_uint16_le(s, rect.bottom); | |
+ index++; | |
+ } | |
+ xrdp_region_delete(reg); | |
+ count = index; | |
+ while (index > 0) | |
+ { | |
+ out_uint8(s, 23); /* qp */ | |
+ out_uint8(s, 100); /* quality level 0..100 */ | |
+ index--; | |
+ } | |
+ s_push_layer(s, mcs_hdr, 0); | |
+ s_pop_layer(s, iso_hdr); | |
+ out_uint32_le(s, count); /* numRegionRects */ | |
+ s_pop_layer(s, mcs_hdr); | |
return 0; | |
} | |
-#endif | |
- | |
-#if defined(XRDP_X264) || defined(XRDP_OPENH264) || defined(XRDP_VANILLA_NVIDIA_CODEC) | |
- | |
-#define AVC444 1 | |
-int | |
-build_rfx_avc420_metablock(struct stream *s, short *rrects, int rcount, int width, int height) | |
+/*****************************************************************************/ | |
+/* called from encoder thread */ | |
+static int | |
+process_enc_h264(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) | |
{ | |
- int index; | |
- int x, y, cx, cy; | |
- struct xrdp_enc_rect rect; | |
- const uint8_t qp = 22; // Default set by Microsoft. | |
- const uint8_t r = 0; // Required to be 0. | |
- const uint8_t p = 0; // Progressively encoded flag. | |
- int qpVal = 0; | |
- qpVal |= qp & 0x3F; | |
- qpVal |= (r & 1) << 6; | |
- qpVal |= (p & 1) << 7; | |
- | |
- out_uint32_le(s, rcount); /* numRegionRects */ | |
- for (index = 0; index < rcount; index++) | |
- { | |
- int location = index * 4; | |
- x = rrects[location + 0]; | |
- y = rrects[location + 1]; | |
- cx = rrects[location + 2]; | |
- cy = rrects[location + 3]; | |
- rect.x = MAX(0, x); | |
- rect.y = MAX(0, y); | |
- rect.cx = MIN(x + cx, width); | |
- rect.cy = MIN(y + cy, height); | |
- /* RDPGFX_RECT16 */ | |
- out_uint16_le(s, rect.x); | |
- out_uint16_le(s, rect.y); | |
- out_uint16_le(s, rect.cx); | |
- out_uint16_le(s, rect.cy); | |
- } | |
- for (index = 0; index < rcount; index++) | |
- { | |
- // 2.2.4.4.2 RDPGFX_AVC420_QUANT_QUALITY | |
- out_uint8(s, qpVal); /* qp */ | |
- out_uint8(s, 100); /* quality level 0..100 (Microsoft uses 100) */ | |
- } | |
- int comp_bytes_pre = 4 + rcount * 8 + rcount * 2; | |
- return comp_bytes_pre; | |
+ LOG_DEVEL(LOG_LEVEL_INFO, "process_enc_h264: dummy func"); | |
+ return 0; | |
} | |
-static XRDP_ENC_DATA_DONE * | |
-build_enc_h264_avc444_yuv420_and_chroma420_stream(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) | |
-{ | |
- int index; | |
- int out_data_bytes; | |
-#if AVC444 | |
- int out_data_bytes1; | |
-#endif | |
- int rcount; | |
- short *rrects; | |
- int error; | |
- char *out_data; | |
- XRDP_ENC_DATA_DONE *enc_done; | |
- struct stream ls; | |
- struct stream *s; | |
- int comp_bytes_pre; | |
-#if AVC444 | |
- int comp_bytes_pre1; | |
#endif | |
- int enc_done_flags; | |
- int scr_width; | |
- int scr_height; | |
- LOG(LOG_LEVEL_DEBUG, "process_enc_x264:"); | |
- LOG(LOG_LEVEL_DEBUG, "process_enc_x264: num_crects %d num_drects %d", | |
- enc->num_crects, enc->num_drects); | |
+/*****************************************************************************/ | |
+static int | |
+gfx_send_done(struct xrdp_encoder *self, XRDP_ENC_DATA *enc, | |
+ int comp_bytes, int pad_bytes, char *comp_pad_data, | |
+ int got_frame_id, int frame_id, int is_last) | |
- scr_width = self->mm->wm->screen->width; | |
- scr_height = self->mm->wm->screen->height; | |
+{ | |
+ XRDP_ENC_DATA_DONE *enc_done; | |
- rcount = enc->num_drects; | |
- rrects = enc->drects; | |
- if (rcount > 15) | |
+ enc_done = g_new0(XRDP_ENC_DATA_DONE, 1); | |
+ if (enc_done == NULL) | |
{ | |
- rcount = enc->num_crects; | |
- rrects = enc->crects; | |
+ return 1; | |
} | |
- | |
- out_data_bytes = 128 * 1024 * 1024; | |
- index = XRDP_SURCMD_PREFIX_BYTES + 16 + 2 + enc->num_drects * 8; | |
- out_data = g_new0(char, out_data_bytes + index); | |
- if (out_data == NULL) | |
+ ENC_SET_BIT(enc_done->flags, ENC_DONE_FLAGS_GFX_BIT); | |
+ enc_done->enc = enc; | |
+ enc_done->last = is_last; | |
+ enc_done->pad_bytes = pad_bytes; | |
+ enc_done->comp_bytes = comp_bytes; | |
+ enc_done->comp_pad_data = comp_pad_data; | |
+ if (got_frame_id) | |
{ | |
- return 0; | |
+ ENC_SET_BIT(enc_done->flags, ENC_DONE_FLAGS_FRAME_ID_BIT); | |
+ enc_done->frame_id = frame_id; | |
} | |
+ /* inform main thread done */ | |
+ tc_mutex_lock(self->mutex); | |
+ fifo_add_item(self->fifo_processed, enc_done); | |
+ tc_mutex_unlock(self->mutex); | |
+ /* signal completion for main thread */ | |
+ g_set_wait_obj(self->xrdp_encoder_event_processed); | |
+ return 0; | |
+} | |
+ | |
+/*****************************************************************************/ | |
+static struct stream * | |
+gfx_wiretosurface1(struct xrdp_encoder *self, | |
+ struct xrdp_egfx_bulk *bulk, struct stream *in_s, | |
+ XRDP_ENC_DATA *enc) | |
+{ | |
+#ifdef XRDP_X264 | |
+ int index; | |
+ int surface_id; | |
+ int codec_id; | |
+ int pixel_format; | |
+ int num_rects_d; | |
+ int num_rects_c; | |
+ struct stream *rv; | |
+ short left; | |
+ short top; | |
+ short width; | |
+ short height; | |
+ short twidth; | |
+ short theight; | |
+ int bitmap_data_length; | |
+ int flags; | |
+ struct xrdp_egfx_rect *d_rects; | |
+ struct xrdp_egfx_rect *c_rects; | |
+ struct xrdp_egfx_rect dst_rect; | |
+ int error; | |
+ struct stream ls; | |
+ struct stream *s; | |
+ short *crects; | |
+ struct xrdp_enc_gfx_cmd *enc_gfx_cmd = &(enc->u.gfx); | |
+ int mon_index; | |
s = &ls; | |
g_memset(s, 0, sizeof(struct stream)); | |
- ls.data = out_data + XRDP_SURCMD_PREFIX_BYTES; | |
- ls.p = ls.data; | |
- ls.size = out_data_bytes + index; | |
- | |
-#if AVC444 | |
- out_data_bytes1 = 0; | |
- comp_bytes_pre1 = 0; | |
-#endif | |
- | |
- if (self->gfx) | |
+ s->size = self->max_compressed_bytes; | |
+ s->data = g_new(char, s->size); | |
+ if (s->data == NULL) | |
{ | |
-#if AVC444 | |
- /* size of avc420EncodedBitmapstream1 */ | |
- s_push_layer(s, mcs_hdr, 4); | |
-#endif | |
- /* RFX_AVC420_METABLOCK */ | |
- comp_bytes_pre = build_rfx_avc420_metablock(s, rrects, rcount, | |
- scr_width, scr_height); | |
- enc_done_flags = 1; | |
+ return NULL; | |
} | |
- else | |
+ s->p = s->data; | |
+ if (!s_check_rem(in_s, 11)) | |
{ | |
- out_uint32_le(s, 0); /* flags */ | |
- out_uint32_le(s, 0); /* session id */ | |
- out_uint16_le(s, enc->width); /* src_width */ | |
- out_uint16_le(s, enc->height); /* src_height */ | |
- out_uint16_le(s, enc->width); /* dst_width */ | |
- out_uint16_le(s, enc->height); /* dst_height */ | |
- out_uint16_le(s, rcount); | |
- for (index = 0; index < rcount; index++) | |
- { | |
- out_uint16_le(s, rrects[index * 4 + 0]); | |
- out_uint16_le(s, rrects[index * 4 + 1]); | |
- out_uint16_le(s, rrects[index * 4 + 2]); | |
- out_uint16_le(s, rrects[index * 4 + 3]); | |
- } | |
- s_push_layer(s, iso_hdr, 4); | |
- comp_bytes_pre = 4 + 4 + 2 + 2 + 2 + 2 + 2 + rcount * 8 + 4; | |
- enc_done_flags = 0; | |
+ g_free(s->data); | |
+ return NULL; | |
} | |
- error = 0; | |
- if (enc->flags & 1) | |
+ in_uint16_le(in_s, surface_id); | |
+ in_uint16_le(in_s, codec_id); | |
+ in_uint8(in_s, pixel_format); | |
+ in_uint32_le(in_s, flags); | |
+ mon_index = (flags >> 28) & 0xF; | |
+ in_uint16_le(in_s, num_rects_d); | |
+ if ((num_rects_d < 1) || (num_rects_d > 16 * 1024) || | |
+ (!s_check_rem(in_s, num_rects_d * 8))) | |
{ | |
- /* already compressed */ | |
- uint8_t *ud = (uint8_t *) (enc->data); | |
- int cbytes = ud[0] | (ud[1] << 8) | (ud[2] << 16) | (ud[3] << 24); | |
- if ((cbytes < 1) || (cbytes > out_data_bytes)) | |
- { | |
- LOG(LOG_LEVEL_INFO, "process_enc_h264: bad h264 bytes %d", cbytes); | |
- g_free(out_data); | |
- return 0; | |
- } | |
- LOG(LOG_LEVEL_DEBUG, | |
- "process_enc_h264: already compressed and size is %d", cbytes); | |
- out_data_bytes = cbytes; | |
- g_memcpy(s->p, enc->data + 4, out_data_bytes); | |
+ g_free(s->data); | |
+ return NULL; | |
} | |
- else | |
+ d_rects = g_new0(struct xrdp_egfx_rect, num_rects_d); | |
+ if (d_rects == NULL) | |
{ | |
-#if defined(XRDP_X264) | |
- error = xrdp_encoder_x264_encode(self->codec_handle, 0, | |
- enc->width, enc->height, 0, | |
- enc->data, | |
- s->p, &out_data_bytes); | |
-#elif defined(XRDP_OPENH264) | |
- error = xrdp_encoder_openh264_encode(self->codec_handle, 0, | |
- enc->width, enc->height, 0, | |
- enc->data, | |
- s->p, &out_data_bytes); | |
-#endif | |
+ g_free(s->data); | |
+ return NULL; | |
} | |
- LOG_DEVEL(LOG_LEVEL_TRACE, | |
- "process_enc_h264: xrdp_encoder_x264_encode rv %d " | |
- "out_data_bytes %d width %d height %d", | |
- error, out_data_bytes, enc->width, enc->height); | |
- if (error != 0) | |
+ for (index = 0; index < num_rects_d; index++) | |
{ | |
- LOG_DEVEL(LOG_LEVEL_TRACE, | |
- "process_enc_h264: xrdp_encoder_x264_encode failed rv %d", | |
- error); | |
- g_free(out_data); | |
- return 0; | |
- } | |
+ in_uint16_le(in_s, left); | |
+ in_uint16_le(in_s, top); | |
+ in_uint16_le(in_s, width); | |
+ in_uint16_le(in_s, height); | |
+ d_rects[index].x1 = left; | |
+ d_rects[index].y1 = top; | |
+ d_rects[index].x2 = left + width; | |
+ d_rects[index].y2 = top + height; | |
-#if AVC444 | |
- s->p += out_data_bytes; | |
- // TODO: Specify LC code here | |
- uint8_t LC = 0b00; | |
- uint32_t bitstream = | |
- ((uint32_t)(comp_bytes_pre + out_data_bytes) & 0x3FFFFFFFUL) | |
- | ((LC & 0x03UL) << 30UL); | |
- /* chroma 444 */ | |
- comp_bytes_pre1 = build_rfx_avc420_metablock(s, rrects, rcount, | |
- scr_width, scr_height); | |
- out_data_bytes1 = 128 * 1024 * 1024; | |
- | |
- if (enc->flags & 1) | |
- { | |
- /* already compressed */ | |
- uint8_t *ud = (uint8_t *) (enc->data); | |
- int cbytes = ud[0] | (ud[1] << 8) | (ud[2] << 16) | (ud[3] << 24); | |
- if ((cbytes < 1) || (cbytes > out_data_bytes)) | |
- { | |
- LOG(LOG_LEVEL_INFO, "process_enc_h264: bad h264 bytes %d", cbytes); | |
- g_free(out_data); | |
- return 0; | |
- } | |
- LOG(LOG_LEVEL_DEBUG, | |
- "process_enc_h264: already compressed and size is %d", cbytes); | |
- out_data_bytes = cbytes; | |
- g_memcpy(s->p, enc->data + 4, out_data_bytes); | |
} | |
- else | |
+ if (!s_check_rem(in_s, 2)) | |
{ | |
-#if defined(XRDP_X264) | |
- error = xrdp_encoder_x264_encode(self->codec_handle, 0, | |
- enc->width, enc->height, 0, | |
- enc->data | |
- + (enc->height * enc->width) * 3 / 2, | |
- s->p, &out_data_bytes1); | |
-#elif defined(XRDP_OPENH264) | |
- error = xrdp_encoder_openh264_encode(self->codec_handle, 0, | |
- enc->width, enc->height, 0, | |
- enc->data | |
- + (enc->height * enc->width) * 3 / 2, | |
- s->p, &out_data_bytes1); | |
-#endif | |
+ g_free(s->data); | |
+ g_free(d_rects); | |
+ return NULL; | |
} | |
- if (error != 0) | |
+ in_uint16_le(in_s, num_rects_c); | |
+ if ((num_rects_c < 1) || (num_rects_c > 16 * 1024) || | |
+ (!s_check_rem(in_s, num_rects_c * 8))) | |
{ | |
- LOG_DEVEL(LOG_LEVEL_TRACE, | |
- "process_enc_h264: xrdp_encoder_x264_encode failed rv %d", | |
- error); | |
- g_free(out_data); | |
- return 0; | |
+ g_free(s->data); | |
+ g_free(d_rects); | |
+ return NULL; | |
} | |
- s->p += out_data_bytes1; | |
- s_push_layer(s, sec_hdr, 0); | |
- s_pop_layer(s, mcs_hdr); | |
- out_uint32_le(s, bitstream); | |
- s_pop_layer(s, sec_hdr); | |
- | |
- s->end = s->p; | |
-#else | |
- s->end = s->p + out_data_bytes; | |
-#endif | |
- | |
- if (s->iso_hdr != NULL) | |
+ c_rects = g_new0(struct xrdp_egfx_rect, num_rects_c); | |
+ if (c_rects == NULL) | |
{ | |
- /* not used in gfx */ | |
- s_pop_layer(s, iso_hdr); | |
- out_uint32_le(s, out_data_bytes); | |
+ g_free(s->data); | |
+ g_free(d_rects); | |
+ return NULL; | |
} | |
- | |
-#if SAVE_VIDEO | |
- n_save_data(s->p, out_data_bytes, enc->width, enc->height); | |
-#endif | |
- | |
- enc_done = g_new0(XRDP_ENC_DATA_DONE, 1); | |
- if (enc_done == NULL) | |
+ crects = g_new(short, num_rects_c * 4); | |
+ if (crects == NULL) | |
{ | |
- return 0; | |
+ g_free(s->data); | |
+ g_free(c_rects); | |
+ g_free(d_rects); | |
+ return NULL; | |
} | |
-#if AVC444 | |
- enc_done->comp_bytes1 = 4 + comp_bytes_pre | |
- + out_data_bytes | |
- + comp_bytes_pre1 | |
- + out_data_bytes1; | |
-#else | |
- enc_done->comp_bytes = comp_bytes_pre + out_data_bytes; | |
-#endif | |
- enc_done->pad_bytes1 = XRDP_SURCMD_PREFIX_BYTES; | |
- enc_done->comp_pad_data1 = out_data; | |
- enc_done->enc = enc; | |
- enc_done->last = 1; | |
- enc_done->rect.cx = scr_width; | |
- enc_done->rect.cy = scr_height; | |
- enc_done->flags = enc_done_flags; | |
- | |
-#if 0 | |
- g_writeln("comp_bytes_pre %d out_data_bytes %d comp_bytes_pre1 %d out_data_bytes1 %d", | |
- comp_bytes_pre, out_data_bytes, comp_bytes_pre1, out_data_bytes1); | |
- g_hexdump(enc_done->comp_pad_data + enc_done->pad_bytes, enc_done->comp_bytes); | |
-#endif | |
- return enc_done; | |
-} | |
- | |
-#if AVC444 | |
- | |
-static XRDP_ENC_DATA_DONE * | |
-build_enc_h264_avc444_yuv420_stream(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) | |
-{ | |
- if (!self->gfx) | |
+ g_memcpy(crects, in_s->p, num_rects_c * 2 * 4); | |
+ for (index = 0; index < num_rects_c; index++) | |
{ | |
- return 0; | |
+ in_uint16_le(in_s, left); | |
+ in_uint16_le(in_s, top); | |
+ in_uint16_le(in_s, width); | |
+ in_uint16_le(in_s, height); | |
+ c_rects[index].x1 = left; | |
+ c_rects[index].y1 = top; | |
+ c_rects[index].x2 = left + width; | |
+ c_rects[index].y2 = top + height; | |
} | |
- | |
- int index; | |
- int out_data_bytes; | |
- int rcount; | |
- short *rrects; | |
- int error; | |
- char *out_data; | |
- XRDP_ENC_DATA_DONE *enc_done; | |
- struct stream ls; | |
- struct stream *s; | |
- int comp_bytes_pre; | |
- int enc_done_flags; | |
- int scr_width, scr_height; | |
- | |
- LOG(LOG_LEVEL_DEBUG, "build_enc_h264_avc444_yuv420_stream:"); | |
- LOG(LOG_LEVEL_DEBUG, "build_enc_h264_avc444_yuv420_stream: num_crects %d num_drects %d", | |
- enc->num_crects, enc->num_drects); | |
- | |
- scr_width = self->mm->wm->screen->width; | |
- scr_height = self->mm->wm->screen->height; | |
- | |
- rcount = enc->num_drects; | |
- rrects = enc->drects; | |
- if (rcount > 15) | |
+ if (!s_check_rem(in_s, 8)) | |
{ | |
- rcount = enc->num_crects; | |
- rrects = enc->crects; | |
+ g_free(s->data); | |
+ g_free(c_rects); | |
+ g_free(d_rects); | |
+ g_free(crects); | |
+ return NULL; | |
} | |
- | |
- out_data_bytes = 128 * 1024 * 1024; | |
- index = XRDP_SURCMD_PREFIX_BYTES + 16 + 2 + rcount * 8; | |
- out_data = g_new(char, out_data_bytes + index); | |
- if (out_data == NULL) | |
+ in_uint16_le(in_s, left); | |
+ in_uint16_le(in_s, top); | |
+ in_uint16_le(in_s, width); | |
+ in_uint16_le(in_s, height); | |
+ twidth = width; | |
+ theight = height; | |
+ dst_rect.x1 = 0; | |
+ dst_rect.y1 = 0; | |
+ dst_rect.x2 = width; | |
+ dst_rect.y2 = height; | |
+ LOG_DEVEL(LOG_LEVEL_INFO, "gfx_wiretosurface1: left %d top " | |
+ "%d width %d height %d mon_index %d", | |
+ left, top, width, height, mon_index); | |
+ /* RFX_AVC420_METABLOCK */ | |
+ if (out_RFX_AVC420_METABLOCK(&dst_rect, s, d_rects, num_rects_d) != 0) | |
{ | |
- return 0; | |
+ g_free(s->data); | |
+ g_free(c_rects); | |
+ g_free(d_rects); | |
+ g_free(crects); | |
+ LOG(LOG_LEVEL_INFO, "10"); | |
+ return NULL; | |
} | |
- s = &ls; | |
- g_memset(s, 0, sizeof(struct stream)); | |
- ls.data = out_data + XRDP_SURCMD_PREFIX_BYTES; | |
- ls.p = ls.data; | |
- ls.size = out_data_bytes + index; | |
+ g_free(c_rects); | |
+ g_free(d_rects); | |
- /* size of avc420EncodedBitmapstream1 */ | |
- s_push_layer(s, mcs_hdr, 4); | |
- /* RFX_AVC420_METABLOCK */ | |
- comp_bytes_pre = build_rfx_avc420_metablock(s, rrects, rcount, scr_width, scr_height); | |
- enc_done_flags = 1; | |
- | |
- error = 0; | |
- if (enc->flags & 1) | |
+ if (ENC_IS_BIT_SET(flags, 0)) | |
{ | |
/* already compressed */ | |
- uint8_t *ud = (uint8_t *) (enc->data); | |
- int cbytes = ud[0] | (ud[1] << 8) | (ud[2] << 16) | (ud[3] << 24); | |
- if ((cbytes < 1) || (cbytes > out_data_bytes)) | |
- { | |
- LOG(LOG_LEVEL_INFO, "process_enc_h264: bad h264 bytes %d", cbytes); | |
- g_free(out_data); | |
- return 0; | |
- } | |
- LOG(LOG_LEVEL_DEBUG, | |
- "process_enc_h264: already compressed and size is %d", cbytes); | |
- out_data_bytes = cbytes; | |
- g_memcpy(s->p, enc->data + 4, out_data_bytes); | |
+ out_uint8a(s, enc_gfx_cmd->data, enc_gfx_cmd->data_bytes); | |
} | |
else | |
{ | |
-#if defined(XRDP_VANILLA_NVIDIA_CODEC) | |
- error = xrdp_encoder_nvenc_encode(self->codec_handle, 0, | |
- enc->width, enc->height, 0, | |
- enc->data, | |
- s->p, &out_data_bytes); | |
-#elif defined(XRDP_X264) | |
- error = xrdp_encoder_x264_encode(self->codec_handle, 0, | |
- enc->width, enc->height, 0, | |
- enc->data, | |
- s->p, &out_data_bytes); | |
-#elif defined(XRDP_OPENH264) | |
- error = xrdp_encoder_openh264_encode(self->codec_handle, 0, | |
- enc->width, enc->height, 0, | |
- enc->data, | |
- s->p, &out_data_bytes); | |
-#endif | |
- } | |
- LOG(LOG_LEVEL_INFO, | |
- "process_enc_h264: xrdp_encoder_nvenc_encode_yuv420 rv %d " | |
- "out_data_bytes %d width %d height %d", | |
- error, out_data_bytes, enc->width, enc->height); | |
- if (error != 0) | |
- { | |
- LOG_DEVEL(LOG_LEVEL_TRACE, | |
- "process_enc_h264: xrdp_encoder_x264_encode failed rv %d", | |
- error); | |
- g_free(out_data); | |
- return 0; | |
+ /* assume NV12 format */ | |
+ if (twidth * theight * 3 / 2 > enc_gfx_cmd->data_bytes) | |
+ { | |
+ g_free(s->data); | |
+ g_free(crects); | |
+ return NULL; | |
+ } | |
+ bitmap_data_length = s_rem_out(s); | |
+ if (self->codec_handle_h264_gfx[mon_index] == NULL) | |
+ { | |
+ self->codec_handle_h264_gfx[mon_index] = | |
+ xrdp_encoder_x264_create(); | |
+ if (self->codec_handle_h264_gfx[mon_index] == NULL) | |
+ { | |
+ g_free(s->data); | |
+ g_free(crects); | |
+ return NULL; | |
+ } | |
+ } | |
+ error = xrdp_encoder_x264_encode( | |
+ self->codec_handle_h264_gfx[mon_index], 0, | |
+ 0, 0, | |
+ width, height, twidth, theight, 0, | |
+ enc_gfx_cmd->data, | |
+ crects, num_rects_c, | |
+ s->p, &bitmap_data_length, NULL); | |
+ if (error == 0) | |
+ { | |
+ xstream_seek(s, bitmap_data_length); | |
+ } | |
+ else | |
+ { | |
+ g_free(s->data); | |
+ g_free(crects); | |
+ return NULL; | |
+ } | |
} | |
- | |
-#if SAVE_VIDEO | |
- n_save_data(s->p, out_data_bytes, enc->width, enc->height); | |
+ s_mark_end(s); | |
+ bitmap_data_length = (int) (s->end - s->data); | |
+ rv = xrdp_egfx_wire_to_surface1(bulk, surface_id, | |
+ codec_id, | |
+ pixel_format, &dst_rect, | |
+ s->data, bitmap_data_length); | |
+ g_free(s->data); | |
+ g_free(crects); | |
+ return rv; | |
+#else | |
+ (void)self; | |
+ (void)bulk; | |
+ (void)in_s; | |
+ (void)enc; | |
+ return NULL; | |
#endif | |
+} | |
- s->p += out_data_bytes; | |
- | |
- s_push_layer(s, sec_hdr, 0); | |
- s_pop_layer(s, mcs_hdr); | |
- // TODO: Specify LC code here | |
- const uint8_t LC = 0x01; | |
- uint32_t bitstream = | |
- ((uint32_t)(comp_bytes_pre + out_data_bytes) & 0x3FFFFFFFUL) | |
- | ((LC & 0x03UL) << 30UL); | |
- out_uint32_le(s, bitstream); | |
- s_pop_layer(s, sec_hdr); | |
- | |
- s->end = s->p; | |
+/*****************************************************************************/ | |
+static struct stream * | |
+gfx_wiretosurface2(struct xrdp_encoder *self, | |
+ struct xrdp_egfx_bulk *bulk, struct stream *in_s, | |
+ XRDP_ENC_DATA *enc) | |
+{ | |
+#ifdef XRDP_RFXCODEC | |
+ int index; | |
+ int surface_id; | |
+ int codec_id; | |
+ int codec_context_id; | |
+ int pixel_format; | |
+ int num_rects_d; | |
+ int num_rects_c; | |
+ struct stream *rv; | |
+ short left; | |
+ short top; | |
+ short width; | |
+ short height; | |
+ char *bitmap_data; | |
+ int bitmap_data_length; | |
+ struct rfx_tile *tiles; | |
+ struct rfx_rect *rfxrects; | |
+ int tiles_compressed; | |
+ int flags; | |
+ int total_tiles; | |
+ int tiles_written; | |
+ int mon_index; | |
- if (s->iso_hdr != NULL) | |
+ if (!s_check_rem(in_s, 15)) | |
{ | |
- /* not used in gfx */ | |
- s_pop_layer(s, iso_hdr); | |
- out_uint32_le(s, out_data_bytes); | |
+ return NULL; | |
} | |
- | |
- enc_done = g_new0(XRDP_ENC_DATA_DONE, 1); | |
- if (enc_done == NULL) | |
+ in_uint16_le(in_s, surface_id); | |
+ in_uint16_le(in_s, codec_id); | |
+ in_uint32_le(in_s, codec_context_id); | |
+ in_uint8(in_s, pixel_format); | |
+ in_uint32_le(in_s, flags); | |
+ mon_index = (flags >> 28) & 0xF; | |
+ in_uint16_le(in_s, num_rects_d); | |
+ if ((num_rects_d < 1) || (num_rects_d > 16 * 1024) || | |
+ (!s_check_rem(in_s, num_rects_d * 8))) | |
{ | |
- return 0; | |
+ return NULL; | |
} | |
- enc_done->out_data_bytes1 = out_data_bytes; | |
- enc_done->comp_bytes1 = 4 + comp_bytes_pre + out_data_bytes; | |
- enc_done->pad_bytes1 = 256; | |
- enc_done->comp_pad_data1 = out_data; | |
- enc_done->enc = enc; | |
- enc_done->last = 1; | |
- enc_done->rect.cx = scr_width; | |
- enc_done->rect.cy = scr_height; | |
- enc_done->flags = enc_done_flags; | |
- | |
- return enc_done; | |
-} | |
- | |
-static XRDP_ENC_DATA_DONE * | |
-build_enc_h264_avc444_chroma420_stream(struct xrdp_encoder *self, XRDP_ENC_DATA *enc, XRDP_ENC_DATA_DONE *enc_done) | |
-{ | |
- if (!self->gfx) | |
+ rfxrects = g_new0(struct rfx_rect, num_rects_d); | |
+ if (rfxrects == NULL) | |
{ | |
- return 0; | |
+ return NULL; | |
} | |
- | |
- int index; | |
- int out_data_bytes; | |
- int rcount; | |
- short *rrects; | |
- int error; | |
- char *out_data; | |
- struct stream ls; | |
- struct stream *s; | |
- int comp_bytes_pre; | |
- int scr_width, scr_height; | |
- | |
- LOG(LOG_LEVEL_DEBUG, "build_enc_h264_avc444_chroma420_stream:"); | |
- LOG(LOG_LEVEL_DEBUG, "build_enc_h264_avc444_chroma420_stream: num_crects %d num_drects %d", | |
- enc->num_crects, enc->num_drects); | |
- | |
- scr_width = self->mm->wm->screen->width; | |
- scr_height = self->mm->wm->screen->height; | |
- | |
- rcount = enc->num_drects; | |
- rrects = enc->drects; | |
- if (rcount > 15) | |
+ for (index = 0; index < num_rects_d; index++) | |
{ | |
- rcount = enc->num_crects; | |
- rrects = enc->crects; | |
+ in_uint16_le(in_s, left); | |
+ in_uint16_le(in_s, top); | |
+ in_uint16_le(in_s, width); | |
+ in_uint16_le(in_s, height); | |
+ rfxrects[index].x = left; | |
+ rfxrects[index].y = top; | |
+ rfxrects[index].cx = width; | |
+ rfxrects[index].cy = height; | |
} | |
- | |
- out_data_bytes = 128 * 1024 * 1024; | |
- index = XRDP_SURCMD_PREFIX_BYTES + 16 + 2 + rcount * 8; | |
- out_data = g_new0(char, out_data_bytes + index); | |
- if (out_data == NULL) | |
+ if (!s_check_rem(in_s, 2)) | |
{ | |
- return 0; | |
+ g_free(rfxrects); | |
+ return NULL; | |
} | |
- | |
- s = &ls; | |
- g_memset(s, 0, sizeof(struct stream)); | |
- ls.data = out_data + XRDP_SURCMD_PREFIX_BYTES; | |
- ls.p = ls.data; | |
- ls.size = out_data_bytes + index; | |
- | |
- /* size of avc420EncodedBitmapstream1 */ | |
- s_push_layer(s, mcs_hdr, 4); | |
- /* RFX_AVC420_METABLOCK */ | |
- comp_bytes_pre = build_rfx_avc420_metablock(s, rrects, rcount, scr_width, scr_height); | |
- error = 0; | |
- if (enc->flags & 1) | |
+ in_uint16_le(in_s, num_rects_c); | |
+ if ((num_rects_c < 1) || (num_rects_c > 16 * 1024) || | |
+ (!s_check_rem(in_s, num_rects_c * 8))) | |
{ | |
- /* already compressed */ | |
- uint8_t *ud = (uint8_t *) (enc->data + enc_done->out_data_bytes1 + 4); | |
- int cbytes = ud[0] | (ud[1] << 8) | (ud[2] << 16) | (ud[3] << 24); | |
- if ((cbytes < 1) || (cbytes > out_data_bytes)) | |
- { | |
- LOG(LOG_LEVEL_INFO, "process_enc_h264: bad h264 bytes %d", cbytes); | |
- g_free(out_data); | |
- return 0; | |
- } | |
- LOG(LOG_LEVEL_DEBUG, | |
- "process_enc_h264: already compressed and size is %d", cbytes); | |
- out_data_bytes = cbytes; | |
- g_memcpy(s->p, enc->data + enc_done->out_data_bytes1 + 8, out_data_bytes); | |
+ g_free(rfxrects); | |
+ return NULL; | |
} | |
- else | |
+ tiles = g_new0(struct rfx_tile, num_rects_c); | |
+ if (tiles == NULL) | |
{ | |
- char *data_position = enc->data + (enc->height * enc->width) * 3 / 2; | |
-#if defined(XRDP_VANILLA_NVIDIA_CODEC) | |
- error = xrdp_encoder_nvenc_encode(self->codec_handle, 0, | |
- enc->width, enc->height, 0, | |
- data_position, | |
- s->p, &out_data_bytes); | |
-#elif defined(XRDP_X264) | |
- error = xrdp_encoder_x264_encode(self->codec_handle, 0, | |
- enc->width, enc->height, 0, | |
- data_position, | |
- s->p, &out_data_bytes); | |
- | |
-#elif defined(XRDP_OPENH264) | |
- error = xrdp_encoder_openh264_encode(self->codec_handle, 0, | |
- enc->width, enc->height, 0, | |
- data_position, | |
- s->p, &out_data_bytes); | |
-#endif | |
+ g_free(rfxrects); | |
+ return NULL; | |
} | |
- LOG(LOG_LEVEL_INFO, | |
- "process_enc_h264: xrdp_encoder_nvenc_encode_chroma420 rv %d " | |
- "out_data_bytes %d width %d height %d", | |
- error, out_data_bytes, enc->width, enc->height); | |
- if (error != 0) | |
+ for (index = 0; index < num_rects_c; index++) | |
{ | |
- LOG_DEVEL(LOG_LEVEL_TRACE, | |
- "process_enc_h264: xrdp_encoder_x264_encode failed rv %d", | |
- error); | |
- g_free(out_data); | |
- return 0; | |
+ in_uint16_le(in_s, left); | |
+ in_uint16_le(in_s, top); | |
+ in_uint16_le(in_s, width); | |
+ in_uint16_le(in_s, height); | |
+ tiles[index].x = left; | |
+ tiles[index].y = top; | |
+ tiles[index].cx = width; | |
+ tiles[index].cy = height; | |
+ tiles[index].quant_y = self->quant_idx_y; | |
+ tiles[index].quant_cb = self->quant_idx_u; | |
+ tiles[index].quant_cr = self->quant_idx_v; | |
} | |
- | |
-#if SAVE_VIDEO | |
- n_save_data(s->p, out_data_bytes, enc->width, enc->height); | |
-#endif | |
- | |
- s->p += out_data_bytes; | |
- | |
- s_push_layer(s, sec_hdr, 0); | |
- s_pop_layer(s, mcs_hdr); | |
- | |
- // TODO: Specify LC code here | |
- const uint8_t LC = 0x02; | |
- const uint32_t bitstream = ((LC & 0x03UL) << 30UL); | |
- | |
- out_uint32_le(s, bitstream); | |
- s_pop_layer(s, sec_hdr); | |
- | |
- s->end = s->p; | |
- | |
- if (s->iso_hdr != NULL) | |
+ if (!s_check_rem(in_s, 8)) | |
{ | |
- /* not used in gfx */ | |
- s_pop_layer(s, iso_hdr); | |
- out_uint32_le(s, out_data_bytes); | |
+ g_free(tiles); | |
+ g_free(rfxrects); | |
+ return NULL; | |
} | |
- | |
- enc_done->out_data_bytes2 = out_data_bytes; | |
- enc_done->comp_bytes2 = 4 + comp_bytes_pre + out_data_bytes; | |
- enc_done->pad_bytes2 = 256; | |
- enc_done->comp_pad_data2 = out_data; | |
- | |
- return enc_done; | |
-} | |
- | |
-#endif | |
- | |
-struct xrdp_enc_rect calculateBoundingBox(short* boxes, int numBoxes) | |
-{ | |
- struct xrdp_enc_rect boundingBox; | |
- boundingBox.x = INT16_MAX; | |
- boundingBox.y = INT16_MAX; | |
- boundingBox.cx = INT16_MIN; | |
- boundingBox.cy = INT16_MIN; | |
- | |
- for (int i = 0; i < numBoxes; ++i) | |
+ in_uint16_le(in_s, left); | |
+ in_uint16_le(in_s, top); | |
+ in_uint16_le(in_s, width); | |
+ in_uint16_le(in_s, height); | |
+ LOG_DEVEL(LOG_LEVEL_INFO, "gfx_wiretosurface2: left %d top " | |
+ "%d width %d height %d mon_index %d", | |
+ left, top, width, height, mon_index); | |
+ if (self->codec_handle_prfx_gfx[mon_index] == NULL) | |
+ { | |
+ self->codec_handle_prfx_gfx[mon_index] = rfxcodec_encode_create( | |
+ width, | |
+ height, | |
+ RFX_FORMAT_YUV, | |
+ RFX_FLAGS_RLGR1 | RFX_FLAGS_PRO1); | |
+ if (self->codec_handle_prfx_gfx[mon_index] == NULL) | |
+ { | |
+ g_free(tiles); | |
+ g_free(rfxrects); | |
+ return NULL; | |
+ } | |
+ } | |
+ bitmap_data_length = self->max_compressed_bytes; | |
+ bitmap_data = g_new(char, bitmap_data_length); | |
+ if (bitmap_data == NULL) | |
{ | |
- int location = i * 4; | |
- short x = boxes[location + 0]; | |
- short y = boxes[location + 1]; | |
- short cx = boxes[location + 2]; | |
- short cy = boxes[location + 3]; | |
- | |
- boundingBox.x = MIN(boundingBox.x, x); | |
- boundingBox.y = MIN(boundingBox.y, y); | |
- boundingBox.cx = MAX(boundingBox.cx, cx); | |
- boundingBox.cy = MAX(boundingBox.cy, cy); | |
+ g_free(tiles); | |
+ g_free(rfxrects); | |
+ return NULL; | |
} | |
- | |
- return boundingBox; | |
-} | |
- | |
-/*****************************************************************************/ | |
-/* called from encoder thread */ | |
-static int | |
-process_enc_h264(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) | |
-{ | |
- FIFO *fifo_processed; | |
- tbus mutex; | |
- tbus event_processed; | |
- | |
- fifo_processed = self->fifo_processed; | |
- mutex = self->mutex; | |
- event_processed = self->xrdp_encoder_event_processed; | |
- | |
- XRDP_ENC_DATA_DONE *enc_done; | |
- int mode = 1; | |
- switch (mode) { | |
- case 0: | |
- enc_done = build_enc_h264_avc444_yuv420_and_chroma420_stream(self, enc); | |
+ rv = NULL; | |
+ tiles_written = 0; | |
+ total_tiles = num_rects_c; | |
+ for (;;) | |
+ { | |
+ tiles_compressed = | |
+ rfxcodec_encode(self->codec_handle_prfx_gfx[mon_index], | |
+ bitmap_data, | |
+ &bitmap_data_length, | |
+ enc->u.gfx.data, | |
+ width, height, | |
+ ((width + 63) & ~63) * 4, | |
+ rfxrects, num_rects_d, | |
+ tiles + tiles_written, total_tiles - tiles_written, | |
+ self->quants, self->num_quants); | |
+ if (tiles_compressed < 1) | |
+ { | |
+ break; | |
+ } | |
+ tiles_written += tiles_compressed; | |
+ rv = xrdp_egfx_wire_to_surface2(bulk, surface_id, | |
+ codec_id, codec_context_id, | |
+ pixel_format, | |
+ bitmap_data, bitmap_data_length); | |
+ if (rv == NULL) | |
+ { | |
+ break; | |
+ } | |
+ LOG_DEVEL(LOG_LEVEL_INFO, "gfx_wiretosurface2: " | |
+ "tiles_compressed %d total_tiles %d tiles_written %d", | |
+ tiles_compressed, total_tiles, | |
+ tiles_written); | |
+ if (tiles_written >= total_tiles) | |
+ { | |
+ /* ok, done with last tile set */ | |
break; | |
- case 1: | |
- enc_done = build_enc_h264_avc444_yuv420_stream(self, enc); | |
- enc_done = build_enc_h264_avc444_chroma420_stream(self, enc, enc_done); | |
+ } | |
+ /* we have another tile set, send this one to main thread */ | |
+ if (gfx_send_done(self, enc, (int)(rv->end - rv->data), 0, | |
+ rv->data, 0, 0, 0) != 0) | |
+ { | |
+ free_stream(rv); | |
+ rv = NULL; | |
break; | |
+ } | |
+ g_free(rv); /* don't call free_stream() here so s->data is valid */ | |
+ rv = NULL; | |
+ bitmap_data_length = self->max_compressed_bytes; | |
} | |
- | |
- enc_done->rect = calculateBoundingBox(enc->drects, enc->num_drects); | |
- | |
- /* done with msg */ | |
- /* inform main thread done */ | |
- tc_mutex_lock(mutex); | |
- fifo_add_item(fifo_processed, enc_done); | |
- tc_mutex_unlock(mutex); | |
- /* signal completion for main thread */ | |
- g_set_wait_obj(event_processed); | |
- | |
- return 0; | |
-} | |
- | |
+ g_free(tiles); | |
+ g_free(rfxrects); | |
+ g_free(bitmap_data); | |
+ return rv; | |
#else | |
(void)self; | |
(void)bulk; | |
@@ -1668,8 +1480,6 @@ process_enc_egfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) | |
return 0; | |
} | |
-#endif | |
- | |
/** | |
* Encoder thread main loop | |
*****************************************************************************/ | |
-- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment