diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | gst/librfb/gstrfbsrc.c | 15 | ||||
-rw-r--r-- | gst/librfb/rfbdecoder.c | 143 | ||||
-rw-r--r-- | gst/librfb/rfbdecoder.h | 4 |
4 files changed, 122 insertions, 48 deletions
@@ -1,3 +1,11 @@ +2007-11-29 Thijs Vermeir <thijsvermeir@gmail.com> + + * gst/librfb/gstrfbsrc.c: + * gst/librfb/rfbdecoder.c: + * gst/librfb/rfbdecoder.h: + Disable CopyRect encoding by default + Add RRE encoding + 2007-11-29 Wim Taymans <wim.taymans@gmail.com> Patch by: Wouter Cloetens <wouter at mind dot be> diff --git a/gst/librfb/gstrfbsrc.c b/gst/librfb/gstrfbsrc.c index 1106cbe4..d3f799cd 100644 --- a/gst/librfb/gstrfbsrc.c +++ b/gst/librfb/gstrfbsrc.c @@ -43,6 +43,7 @@ enum ARG_WIDTH, ARG_HEIGHT, ARG_INCREMENTAL, + ARG_USE_COPYRECT }; GST_DEBUG_CATEGORY_STATIC (rfbsrc_debug); @@ -140,7 +141,9 @@ gst_rfb_src_class_init (GstRfbSrcClass * klass) g_object_class_install_property (gobject_class, ARG_INCREMENTAL, g_param_spec_boolean ("incremental", "Incremental updates", "Incremental updates", TRUE, G_PARAM_READWRITE)); - + g_object_class_install_property (gobject_class, ARG_USE_COPYRECT, + g_param_spec_boolean ("use-copyrect", "Use copyrect encoding", + "Use copyrect encoding", FALSE, G_PARAM_READWRITE)); gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_rfb_src_start); gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_rfb_src_stop); gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_rfb_src_event); @@ -258,6 +261,9 @@ gst_rfb_src_set_property (GObject * object, guint prop_id, case ARG_INCREMENTAL: src->incremental_update = g_value_get_boolean (value); break; + case ARG_USE_COPYRECT: + src->decoder->use_copyrect = g_value_get_boolean (value); + break; default: break; } @@ -297,6 +303,9 @@ gst_rfb_src_get_property (GObject * object, guint prop_id, case ARG_INCREMENTAL: g_value_set_boolean (value, src->incremental_update); break; + case ARG_USE_COPYRECT: + g_value_set_boolean (value, src->decoder->use_copyrect); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -334,7 +343,9 @@ gst_rfb_src_start (GstBaseSrc * bsrc) src->decoder->width * src->decoder->height * (decoder->bpp / 8), NULL); decoder->frame = g_malloc (bsrc->blocksize); - decoder->prev_frame = g_malloc (bsrc->blocksize); + if (decoder->use_copyrect) { + decoder->prev_frame = g_malloc (bsrc->blocksize); + } decoder->decoder_private = src; /* calculate some many used values */ diff --git a/gst/librfb/rfbdecoder.c b/gst/librfb/rfbdecoder.c index 7be4c480..dd7fe3a4 100644 --- a/gst/librfb/rfbdecoder.c +++ b/gst/librfb/rfbdecoder.c @@ -12,6 +12,7 @@ #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> +#include <byteswap.h> #include "vncauth.h" @@ -52,6 +53,8 @@ static void rfb_decoder_raw_encoding (RfbDecoder * decoder, gint start_x, gint start_y, gint rect_w, gint rect_h); static void rfb_decoder_copyrect_encoding (RfbDecoder * decoder, gint start_x, gint start_y, gint rect_w, gint rect_h); +static void rfb_decoder_rre_encoding (RfbDecoder * decoder, gint start_x, + gint start_y, gint rect_w, gint rect_h); RfbDecoder * rfb_decoder_new (void) @@ -62,6 +65,8 @@ rfb_decoder_new (void) decoder->password = NULL; + decoder->use_copyrect = FALSE; + decoder->offset_x = 0; decoder->offset_y = 0; decoder->rect_width = 0; @@ -187,8 +192,10 @@ rfb_decoder_send_update_request (RfbDecoder * decoder, rfb_decoder_send (decoder, data, 10); /* create a backup of the prev frame for copyrect encoding */ - memcpy (decoder->prev_frame, decoder->frame, - decoder->rect_width * decoder->rect_height * decoder->bpp / 8); + if (decoder->use_copyrect) { + memcpy (decoder->prev_frame, decoder->frame, + decoder->rect_width * decoder->rect_height * decoder->bpp / 8); + } decoder->state = rfb_decoder_state_normal; } @@ -387,6 +394,27 @@ rfb_decoder_state_security_result (RfbDecoder * decoder) return TRUE; } +guint8 * +rfb_decoder_message_set_encodings (GSList * encodings_list) +{ + + guint8 *message = g_malloc0 (4 + 4 * g_slist_length (encodings_list)); + + message[0] = 0x02; /* message type */ + RFB_SET_UINT16 (message + 2, g_slist_length (encodings_list)); /* number of encodings */ + + /* write all the encoding types */ + guint32 *encoding_type = (guint32 *) (message + 4); + + while (encodings_list) { + RFB_SET_UINT32 (encoding_type, (guint32) encodings_list->data); + encoding_type++; + encodings_list = encodings_list->next; + } + + return message; +} + /** * rfb_decoder_state_set_encodings: * @decoder: The rfb context @@ -398,21 +426,22 @@ rfb_decoder_state_security_result (RfbDecoder * decoder) static gboolean rfb_decoder_state_set_encodings (RfbDecoder * decoder) { - guint8 *buffer = g_malloc0 (12); // 4 + 4 * nr_of_encodings + GSList *encoder_list = NULL; - GST_DEBUG ("Sending encoding types to server"); + GST_DEBUG ("entered set encodings"); - buffer[0] = 2; // message-type - buffer[3] = 2; // number of encodings - - /* RAW encoding (0) */ + encoder_list = g_slist_append (encoder_list, (guint32 *) ENCODING_TYPE_RRE); + if (decoder->use_copyrect) { + encoder_list = + g_slist_append (encoder_list, (guint32 *) ENCODING_TYPE_COPYRECT); + } + encoder_list = g_slist_append (encoder_list, (guint32 *) ENCODING_TYPE_RAW); - /* CopyRect encoding (1) */ - buffer[11] = 1; + guint8 *message = rfb_decoder_message_set_encodings (encoder_list); - rfb_decoder_send (decoder, buffer, 12); + rfb_decoder_send (decoder, message, 4 + 4 * g_slist_length (encoder_list)); - g_free (buffer); + g_free (message); decoder->state = rfb_decoder_state_normal; decoder->inited = TRUE; @@ -560,40 +589,6 @@ rfb_decoder_state_framebuffer_update (RfbDecoder * decoder) return TRUE; } -/* -static gboolean -rfb_decoder_state_framebuffer_update (RfbDecoder *decoder) -{ - RfbBuffer *buffer; - gint ret; - gint x, y, w, h; - gint encoding; - gint size; - - ret = rfb_bytestream_peek (decoder->bytestream, &buffer, 12); - if (ret < 12) - return FALSE; - - x = RFB_GET_UINT16 (buffer->data + 0); - y = RFB_GET_UINT16 (buffer->data + 2); - w = RFB_GET_UINT16 (buffer->data + 4); - h = RFB_GET_UINT16 (buffer->data + 6); - encoding = RFB_GET_UINT32 (buffer->data + 8); - - GST_DEBUG(" UPDATE Receiver"); - GST_DEBUG("x:%d y:%d", x, y); - GST_DEBUG("w:%d h:%d", w, h); - GST_DEBUG("encoding: %d", encoding); - - switch (encoding) - { - default: - GST_WARNING("encoding type(%d) is not supported", encoding); - return FALSE; - } - return TRUE; -} -*/ static gboolean rfb_decoder_state_framebuffer_update_rectangle (RfbDecoder * decoder) { @@ -621,6 +616,9 @@ rfb_decoder_state_framebuffer_update_rectangle (RfbDecoder * decoder) case ENCODING_TYPE_COPYRECT: rfb_decoder_copyrect_encoding (decoder, x, y, w, h); break; + case ENCODING_TYPE_RRE: + rfb_decoder_rre_encoding (decoder, x, y, w, h); + break; default: g_critical ("unimplemented encoding\n"); break; @@ -696,6 +694,59 @@ rfb_decoder_copyrect_encoding (RfbDecoder * decoder, gint start_x, gint start_y, g_free (buffer); } +static void +rfb_decoder_fill_rectangle (RfbDecoder * decoder, gint x, gint y, gint w, + gint h, guint32 color) +{ + /* fill the whole region with the same color */ + + guint32 *offset; + gint i, j; + + for (i = 0; i < h; i++) { + offset = + (guint32 *) (decoder->frame + ((x + (y + + i) * decoder->rect_width)) * decoder->bytespp); + for (j = 0; j < w; j++) { + *(offset++) = color; + } + } +} + +static void +rfb_decoder_rre_encoding (RfbDecoder * decoder, gint start_x, gint start_y, + gint rect_w, gint rect_h) +{ + guint8 *buffer; + guint32 number_of_rectangles, color; + guint16 x, y, w, h; + + buffer = rfb_decoder_read (decoder, 4 + decoder->bytespp); + number_of_rectangles = RFB_GET_UINT32 (buffer); + color = bswap_32 (RFB_GET_UINT32 (buffer + 4)); + g_free (buffer); + + GST_DEBUG ("number of rectangles :%d", number_of_rectangles); + + /* color the background of this rectangle */ + rfb_decoder_fill_rectangle (decoder, start_x, start_y, rect_w, rect_h, color); + + while (number_of_rectangles--) { + + buffer = rfb_decoder_read (decoder, decoder->bytespp + 8); + color = bswap_32 (RFB_GET_UINT32 (buffer)); + x = RFB_GET_UINT16 (buffer + decoder->bytespp); + y = RFB_GET_UINT16 (buffer + decoder->bytespp + 2); + w = RFB_GET_UINT16 (buffer + decoder->bytespp + 4); + h = RFB_GET_UINT16 (buffer + decoder->bytespp + 6); + + /* draw the rectangle in the foreground */ + rfb_decoder_fill_rectangle (decoder, start_x + x, start_y + y, w, h, color); + + g_free (buffer); + } +} + static gboolean rfb_decoder_state_set_colour_map_entries (RfbDecoder * decoder) { diff --git a/gst/librfb/rfbdecoder.h b/gst/librfb/rfbdecoder.h index dca8d192..4710c8b9 100644 --- a/gst/librfb/rfbdecoder.h +++ b/gst/librfb/rfbdecoder.h @@ -19,6 +19,7 @@ G_BEGIN_DECLS enum #define ENCODING_TYPE_RAW 0 #define ENCODING_TYPE_COPYRECT 1 +#define ENCODING_TYPE_RRE 2 typedef struct _RfbDecoder RfbDecoder; @@ -46,6 +47,7 @@ struct _RfbDecoder guint security_type; gchar *password; + gboolean use_copyrect; guint width; guint height; @@ -102,6 +104,8 @@ void rfb_decoder_send_key_event (RfbDecoder * decoder, guint key, gboolean down_flag); void rfb_decoder_send_pointer_event (RfbDecoder * decoder, gint button_mask, gint x, gint y); +guint8 * + rfb_decoder_message_set_encodings ( GSList *encodings_list); G_END_DECLS #endif |