From 798aca639be11d2001a6c82b4d0eb5c6a453ce3c Mon Sep 17 00:00:00 2001 From: Thijs Vermeir Date: Wed, 5 Nov 2008 22:25:25 +0000 Subject: gst/librfb/: Add Hextile encoding Original commit message from CVS: * gst/librfb/gstrfbsrc.c: * gst/librfb/rfbdecoder.c: * gst/librfb/rfbdecoder.h: Add Hextile encoding --- ChangeLog | 7 ++ gst/librfb/gstrfbsrc.c | 25 ++-- gst/librfb/rfbdecoder.c | 304 ++++++++++++++++++++++++++++-------------------- gst/librfb/rfbdecoder.h | 9 ++ 4 files changed, 202 insertions(+), 143 deletions(-) diff --git a/ChangeLog b/ChangeLog index e07adaf9..ee2b8b3f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2008-11-05 Thijs Vermeir + + * gst/librfb/gstrfbsrc.c: + * gst/librfb/rfbdecoder.c: + * gst/librfb/rfbdecoder.h: + Add Hextile encoding + 2008-11-05 Zaheer Abbas Merali patch by: Josep Torra diff --git a/gst/librfb/gstrfbsrc.c b/gst/librfb/gstrfbsrc.c index fdb03625..0fd62c90 100644 --- a/gst/librfb/gstrfbsrc.c +++ b/gst/librfb/gstrfbsrc.c @@ -49,6 +49,7 @@ enum }; GST_DEBUG_CATEGORY_STATIC (rfbsrc_debug); +GST_DEBUG_CATEGORY (rfbdecoder_debug); #define GST_CAT_DEFAULT rfbsrc_debug static const GstElementDetails gst_rfb_src_details = @@ -88,11 +89,7 @@ static gboolean gst_rfb_src_event (GstBaseSrc * bsrc, GstEvent * event); static GstFlowReturn gst_rfb_src_create (GstPushSrc * psrc, GstBuffer ** outbuf); -#define DEBUG_INIT(bla) \ - GST_DEBUG_CATEGORY_INIT (rfbsrc_debug, "rfbsrc", 0, "rfb src element"); - -GST_BOILERPLATE_FULL (GstRfbSrc, gst_rfb_src, GstPushSrc, GST_TYPE_PUSH_SRC, - DEBUG_INIT); +GST_BOILERPLATE (GstRfbSrc, gst_rfb_src, GstPushSrc, GST_TYPE_PUSH_SRC); static void gst_rfb_src_base_init (gpointer g_class) @@ -112,6 +109,9 @@ gst_rfb_src_class_init (GstRfbSrcClass * klass) GstBaseSrcClass *gstbasesrc_class; GstPushSrcClass *gstpushsrc_class; + GST_DEBUG_CATEGORY_INIT (rfbsrc_debug, "rfbsrc", 0, "rfb src element"); + GST_DEBUG_CATEGORY_INIT (rfbdecoder_debug, "rfbdecoder", 0, "rfb decoder"); + gobject_class = (GObjectClass *) klass; gstbasesrc_class = (GstBaseSrcClass *) klass; gstpushsrc_class = (GstPushSrcClass *) klass; @@ -231,18 +231,7 @@ gst_rfb_property_set_version (GstRfbSrc * src, gchar * value) static gchar * gst_rfb_property_get_version (GstRfbSrc * src) { - gchar *version = g_malloc (8); - gchar *major = g_strdup_printf ("%d", src->version_major); - gchar *minor = g_strdup_printf ("%d", src->version_minor); - - g_stpcpy (version, major); - g_strlcat (version, ".", 8); - g_strlcat (version, minor, 8); - - g_free (major); - g_free (minor); - - return version; + return g_strdup_printf ("%d.%d", src->version_major, src->version_minor); } static void @@ -355,7 +344,7 @@ gst_rfb_src_start (GstBaseSrc * bsrc) GST_DEBUG_OBJECT (src, "connecting to host %s on port %d", src->host, src->port); if (!rfb_decoder_connect_tcp (decoder, src->host, src->port)) { - GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL), + GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), ("Could not connect to host %s on port %d", src->host, src->port)); rfb_decoder_free (decoder); return FALSE; diff --git a/gst/librfb/rfbdecoder.c b/gst/librfb/rfbdecoder.c index d16e584f..4e32cc62 100644 --- a/gst/librfb/rfbdecoder.c +++ b/gst/librfb/rfbdecoder.c @@ -23,7 +23,7 @@ #define RFB_SET_UINT16(ptr, val) (*(guint16 *)(ptr) = GUINT16_TO_BE (val)) #define RFB_SET_UINT8(ptr, val) (*(guint8 *)(ptr) = val) -GST_DEBUG_CATEGORY_STATIC (rfbdecoder_debug); +GST_DEBUG_CATEGORY_EXTERN (rfbdecoder_debug); #define GST_CAT_DEFAULT rfbdecoder_debug #if 0 @@ -56,18 +56,13 @@ static void rfb_decoder_rre_encoding (RfbDecoder * decoder, gint start_x, gint start_y, gint rect_w, gint rect_h); static void rfb_decoder_corre_encoding (RfbDecoder * decoder, gint start_x, gint start_y, gint rect_w, gint rect_h); +static void rfb_decoder_hextile_encoding (RfbDecoder * decoder, gint start_x, + gint start_y, gint rect_w, gint rect_h); RfbDecoder * rfb_decoder_new (void) { RfbDecoder *decoder = g_new0 (RfbDecoder, 1); - static gboolean debug_inited = FALSE; - - if (!debug_inited) { - /* FIXME this is the wrong place to int this */ - GST_DEBUG_CATEGORY_INIT (rfbdecoder_debug, "rfbdecoder", 0, "Rfb source"); - debug_inited = TRUE; - } decoder->fd = -1; @@ -80,6 +75,8 @@ rfb_decoder_new (void) decoder->rect_width = 0; decoder->rect_height = 0; decoder->shared_flag = TRUE; + decoder->data = NULL; + decoder->data_len = 0; return decoder; } @@ -91,6 +88,9 @@ rfb_decoder_free (RfbDecoder * decoder) if (decoder->fd >= 0) close (decoder->fd); + + if (decoder->data) + g_free (decoder->data); } gboolean @@ -152,23 +152,26 @@ rfb_decoder_read (RfbDecoder * decoder, guint32 len) { guint32 total = 0; guint32 now = 0; - guint8 *address = NULL; g_return_val_if_fail (decoder->fd > 0, NULL); g_return_val_if_fail (len > 0, NULL); - address = g_malloc (len); - g_return_val_if_fail (address, NULL); + if (G_UNLIKELY (len > decoder->data_len)) { + if (decoder->data) + g_free (decoder->data); + decoder->data = g_malloc (len); + decoder->data_len = len; + } while (total < len) { - now = recv (decoder->fd, address + total, len - total, 0); + now = recv (decoder->fd, decoder->data + total, len - total, 0); if (now <= 0) { GST_WARNING ("rfb read error on socket"); return NULL; } total += now; } - return address; + return decoder->data; } static gint @@ -251,18 +254,16 @@ rfb_decoder_send_pointer_event (RfbDecoder * decoder, static gboolean rfb_decoder_state_wait_for_protocol_version (RfbDecoder * decoder) { - guint8 *buffer = NULL; + rfb_decoder_read (decoder, 12); - buffer = rfb_decoder_read (decoder, 12); + g_return_val_if_fail (memcmp (decoder->data, "RFB 003.00", 10) == 0, FALSE); + g_return_val_if_fail (*(decoder->data + 11) == 0x0a, FALSE); - g_return_val_if_fail (memcmp (buffer, "RFB 003.00", 10) == 0, FALSE); - g_return_val_if_fail (*(buffer + 11) == 0x0a, FALSE); - - GST_DEBUG ("\"%.11s\"", buffer); - *(buffer + 7) = 0x00; - *(buffer + 11) = 0x00; - decoder->protocol_major = atoi ((char *) (buffer + 4)); - decoder->protocol_minor = atoi ((char *) (buffer + 8)); + GST_DEBUG ("\"%.11s\"", decoder->data); + *(decoder->data) = 0x00; + *(decoder->data + 11) = 0x00; + decoder->protocol_major = atoi ((char *) (decoder->data + 4)); + decoder->protocol_minor = atoi ((char *) (decoder->data + 8)); GST_DEBUG ("Major version : %d", decoder->protocol_major); GST_DEBUG ("Minor version : %d", decoder->protocol_minor); @@ -283,7 +284,6 @@ rfb_decoder_state_wait_for_protocol_version (RfbDecoder * decoder) rfb_decoder_send (decoder, (guint8 *) "RFB 003.003\n", 12); decoder->state = rfb_decoder_state_wait_for_security; - g_free (buffer); return TRUE; } @@ -295,17 +295,12 @@ static gboolean rfb_decoder_state_reason (RfbDecoder * decoder) { gint reason_length; - guint8 *buffer = NULL; - - buffer = rfb_decoder_read (decoder, 4); - reason_length = RFB_GET_UINT32 (buffer); - g_free (buffer); - buffer = NULL; - buffer = rfb_decoder_read (decoder, reason_length); - GST_WARNING ("Reason by server: %s", buffer); + rfb_decoder_read (decoder, 4); - g_free (buffer); + reason_length = RFB_GET_UINT32 (decoder->data); + rfb_decoder_read (decoder, reason_length); + GST_WARNING ("Reason by server: %s", decoder->data); return FALSE; } @@ -313,8 +308,6 @@ rfb_decoder_state_reason (RfbDecoder * decoder) static gboolean rfb_decoder_state_wait_for_security (RfbDecoder * decoder) { - guint8 *buffer = NULL; - /* * Version 3.3 The server decides the security type and sends a single word * @@ -323,16 +316,14 @@ rfb_decoder_state_wait_for_security (RfbDecoder * decoder) * above. */ if (IS_VERSION_3_3 (decoder)) { - buffer = rfb_decoder_read (decoder, 4); + rfb_decoder_read (decoder, 4); - decoder->security_type = RFB_GET_UINT32 (buffer); + decoder->security_type = RFB_GET_UINT32 (decoder->data); GST_DEBUG ("security = %d", decoder->security_type); g_return_val_if_fail (decoder->security_type < 3, FALSE); g_return_val_if_fail (decoder->security_type != SECURITY_FAIL, rfb_decoder_state_reason (decoder)); - g_free (buffer); - buffer = NULL; } else { /* \TODO Add behavoir for the rfb 3.7 and 3.8 servers */ GST_WARNING ("Other versions are not yet supported"); @@ -360,10 +351,9 @@ rfb_decoder_state_wait_for_security (RfbDecoder * decoder) return FALSE; } - buffer = rfb_decoder_read (decoder, 16); - vncEncryptBytes ((unsigned char *) buffer, decoder->password); - rfb_decoder_send (decoder, buffer, 16); - g_free (buffer); + rfb_decoder_read (decoder, 16); + vncEncryptBytes ((unsigned char *) decoder->data, decoder->password); + rfb_decoder_send (decoder, decoder->data, 16); GST_DEBUG ("Encrypted challenge send to server"); @@ -384,10 +374,8 @@ rfb_decoder_state_wait_for_security (RfbDecoder * decoder) static gboolean rfb_decoder_state_security_result (RfbDecoder * decoder) { - guint8 *buffer = NULL; - - buffer = rfb_decoder_read (decoder, 4); - if (RFB_GET_UINT32 (buffer) != 0) { + rfb_decoder_read (decoder, 4); + if (RFB_GET_UINT32 (decoder->data) != 0) { GST_WARNING ("Security handshaking failed"); if (IS_VERSION_3_8 (decoder)) { decoder->state = rfb_decoder_state_reason; @@ -440,6 +428,8 @@ rfb_decoder_state_set_encodings (RfbDecoder * decoder) GST_DEBUG ("entered set encodings"); + encoder_list = + g_slist_append (encoder_list, GUINT_TO_POINTER (ENCODING_TYPE_HEXTILE)); encoder_list = g_slist_append (encoder_list, GUINT_TO_POINTER (ENCODING_TYPE_CORRE)); encoder_list = @@ -480,23 +470,22 @@ rfb_decoder_state_send_client_initialisation (RfbDecoder * decoder) static gboolean rfb_decoder_state_wait_for_server_initialisation (RfbDecoder * decoder) { - guint8 *buffer = NULL; guint32 name_length; - buffer = rfb_decoder_read (decoder, 24); - - decoder->width = RFB_GET_UINT16 (buffer + 0); - decoder->height = RFB_GET_UINT16 (buffer + 2); - decoder->bpp = RFB_GET_UINT8 (buffer + 4); - decoder->depth = RFB_GET_UINT8 (buffer + 5); - decoder->big_endian = RFB_GET_UINT8 (buffer + 6); - decoder->true_colour = RFB_GET_UINT8 (buffer + 7); - decoder->red_max = RFB_GET_UINT16 (buffer + 8); - decoder->green_max = RFB_GET_UINT16 (buffer + 10); - decoder->blue_max = RFB_GET_UINT16 (buffer + 12); - decoder->red_shift = RFB_GET_UINT8 (buffer + 14); - decoder->green_shift = RFB_GET_UINT8 (buffer + 15); - decoder->blue_shift = RFB_GET_UINT8 (buffer + 16); + rfb_decoder_read (decoder, 24); + + decoder->width = RFB_GET_UINT16 (decoder->data + 0); + decoder->height = RFB_GET_UINT16 (decoder->data + 2); + decoder->bpp = RFB_GET_UINT8 (decoder->data + 4); + decoder->depth = RFB_GET_UINT8 (decoder->data + 5); + decoder->big_endian = RFB_GET_UINT8 (decoder->data + 6); + decoder->true_colour = RFB_GET_UINT8 (decoder->data + 7); + decoder->red_max = RFB_GET_UINT16 (decoder->data + 8); + decoder->green_max = RFB_GET_UINT16 (decoder->data + 10); + decoder->blue_max = RFB_GET_UINT16 (decoder->data + 12); + decoder->red_shift = RFB_GET_UINT8 (decoder->data + 14); + decoder->green_shift = RFB_GET_UINT8 (decoder->data + 15); + decoder->blue_shift = RFB_GET_UINT8 (decoder->data + 16); GST_DEBUG ("Server Initialization"); GST_DEBUG ("width = %d", decoder->width); @@ -512,12 +501,11 @@ rfb_decoder_state_wait_for_server_initialisation (RfbDecoder * decoder) GST_DEBUG ("green_shift= %d", decoder->green_shift); GST_DEBUG ("blue_shift = %d", decoder->blue_shift); - name_length = RFB_GET_UINT32 (buffer + 20); + name_length = RFB_GET_UINT32 (decoder->data + 20); - buffer = rfb_decoder_read (decoder, name_length); + rfb_decoder_read (decoder, name_length); - decoder->name = g_strndup ((gchar *) (buffer), name_length); - g_free (buffer); + decoder->name = g_strndup ((gchar *) (decoder->data), name_length); GST_DEBUG ("name = %s", decoder->name); /* check if we need cropping */ @@ -558,13 +546,12 @@ rfb_decoder_state_wait_for_server_initialisation (RfbDecoder * decoder) static gboolean rfb_decoder_state_normal (RfbDecoder * decoder) { - guint8 *buffer; gint message_type; GST_DEBUG ("decoder_state_normal"); - buffer = rfb_decoder_read (decoder, 1); - message_type = RFB_GET_UINT8 (buffer); + rfb_decoder_read (decoder, 1); + message_type = RFB_GET_UINT8 (decoder->data); switch (message_type) { case MESSAGE_TYPE_FRAMEBUFFER_UPDATE: @@ -585,18 +572,16 @@ rfb_decoder_state_normal (RfbDecoder * decoder) g_critical ("unknown message type %d", message_type); } - g_free (buffer); return TRUE; } static gboolean rfb_decoder_state_framebuffer_update (RfbDecoder * decoder) { - guint8 *buffer; - buffer = rfb_decoder_read (decoder, 3); + rfb_decoder_read (decoder, 3); - decoder->n_rects = RFB_GET_UINT16 (buffer + 1); + decoder->n_rects = RFB_GET_UINT16 (decoder->data + 1); GST_DEBUG ("Number of rectangles : %d", decoder->n_rects); decoder->state = rfb_decoder_state_framebuffer_update_rectangle; @@ -607,17 +592,16 @@ rfb_decoder_state_framebuffer_update (RfbDecoder * decoder) static gboolean rfb_decoder_state_framebuffer_update_rectangle (RfbDecoder * decoder) { - guint8 *buffer; gint x, y, w, h; gint encoding; - buffer = rfb_decoder_read (decoder, 12); + rfb_decoder_read (decoder, 12); - x = RFB_GET_UINT16 (buffer + 0) - decoder->offset_x; - y = RFB_GET_UINT16 (buffer + 2) - decoder->offset_y; - w = RFB_GET_UINT16 (buffer + 4); - h = RFB_GET_UINT16 (buffer + 6); - encoding = RFB_GET_UINT32 (buffer + 8); + x = RFB_GET_UINT16 (decoder->data + 0) - decoder->offset_x; + y = RFB_GET_UINT16 (decoder->data + 2) - decoder->offset_y; + w = RFB_GET_UINT16 (decoder->data + 4); + h = RFB_GET_UINT16 (decoder->data + 6); + encoding = RFB_GET_UINT32 (decoder->data + 8); GST_DEBUG ("update recieved"); GST_DEBUG ("x:%d y:%d", x, y); @@ -637,11 +621,13 @@ rfb_decoder_state_framebuffer_update_rectangle (RfbDecoder * decoder) case ENCODING_TYPE_CORRE: rfb_decoder_corre_encoding (decoder, x, y, w, h); break; + case ENCODING_TYPE_HEXTILE: + rfb_decoder_hextile_encoding (decoder, x, y, w, h); + break; default: g_critical ("unimplemented encoding\n"); break; } - g_free (buffer); decoder->n_rects--; if (decoder->n_rects == 0) { decoder->state = NULL; @@ -656,26 +642,24 @@ rfb_decoder_raw_encoding (RfbDecoder * decoder, gint start_x, gint start_y, gint rect_w, gint rect_h) { gint size; - guint8 *frame, *buffer, *p; + guint8 *frame, *p; guint32 raw_line_size; raw_line_size = rect_w * decoder->bytespp; size = rect_h * raw_line_size; - GST_DEBUG ("Reading %d bytes", size); - buffer = rfb_decoder_read (decoder, size); + GST_DEBUG ("Reading %d bytes (%dx%d)", size, rect_w, rect_h); + rfb_decoder_read (decoder, size); frame = decoder->frame + (((start_y * decoder->rect_width) + start_x) * decoder->bytespp); - p = buffer; + p = decoder->data; while (rect_h--) { memcpy (frame, p, raw_line_size); p += raw_line_size; frame += decoder->line_size; } - - g_free (buffer); } static void @@ -684,14 +668,13 @@ rfb_decoder_copyrect_encoding (RfbDecoder * decoder, gint start_x, gint start_y, { guint16 src_x, src_y; gint line_width, copyrect_width; - guint8 *buffer; guint8 *src, *dst; - buffer = rfb_decoder_read (decoder, 4); + rfb_decoder_read (decoder, 4); /* don't forget the offset */ - src_x = RFB_GET_UINT16 (buffer) - decoder->offset_x; - src_y = RFB_GET_UINT16 (buffer + 2) - decoder->offset_y; + src_x = RFB_GET_UINT16 (decoder->data) - decoder->offset_x; + src_y = RFB_GET_UINT16 (decoder->data + 2) - decoder->offset_y; GST_DEBUG ("Copyrect from %d %d", src_x, src_y); copyrect_width = rect_w * decoder->bytespp; @@ -708,8 +691,6 @@ rfb_decoder_copyrect_encoding (RfbDecoder * decoder, gint start_x, gint start_y, src += line_width; dst += line_width; } - - g_free (buffer); } static void @@ -735,14 +716,12 @@ 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 = GUINT32_SWAP_LE_BE ((RFB_GET_UINT32 (buffer + 4))); - g_free (buffer); + rfb_decoder_read (decoder, 4 + decoder->bytespp); + number_of_rectangles = RFB_GET_UINT32 (decoder->data); + color = GUINT32_SWAP_LE_BE ((RFB_GET_UINT32 (decoder->data + 4))); GST_DEBUG ("number of rectangles :%d", number_of_rectangles); @@ -751,17 +730,15 @@ rfb_decoder_rre_encoding (RfbDecoder * decoder, gint start_x, gint start_y, while (number_of_rectangles--) { - buffer = rfb_decoder_read (decoder, decoder->bytespp + 8); - color = GUINT32_SWAP_LE_BE ((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); + rfb_decoder_read (decoder, decoder->bytespp + 8); + color = GUINT32_SWAP_LE_BE ((RFB_GET_UINT32 (decoder->data))); + x = RFB_GET_UINT16 (decoder->data + decoder->bytespp); + y = RFB_GET_UINT16 (decoder->data + decoder->bytespp + 2); + w = RFB_GET_UINT16 (decoder->data + decoder->bytespp + 4); + h = RFB_GET_UINT16 (decoder->data + 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); } } @@ -769,14 +746,13 @@ static void rfb_decoder_corre_encoding (RfbDecoder * decoder, gint start_x, gint start_y, gint rect_w, gint rect_h) { - guint8 *buffer; guint32 number_of_rectangles, color; guint8 x, y, w, h; - buffer = rfb_decoder_read (decoder, 4 + decoder->bytespp); - number_of_rectangles = RFB_GET_UINT32 (buffer); - color = GUINT32_SWAP_LE_BE ((RFB_GET_UINT32 (buffer + 4))); - g_free (buffer); + rfb_decoder_read (decoder, 4 + decoder->bytespp); + number_of_rectangles = RFB_GET_UINT32 (decoder->data); + color = GUINT32_SWAP_LE_BE ((RFB_GET_UINT32 (decoder->data + 4))); + g_free (decoder->data); GST_DEBUG ("number of rectangles :%d", number_of_rectangles); @@ -785,17 +761,97 @@ rfb_decoder_corre_encoding (RfbDecoder * decoder, gint start_x, gint start_y, while (number_of_rectangles--) { - buffer = rfb_decoder_read (decoder, decoder->bytespp + 8); - color = GUINT32_SWAP_LE_BE ((RFB_GET_UINT32 (buffer))); - x = RFB_GET_UINT8 (buffer + decoder->bytespp); - y = RFB_GET_UINT8 (buffer + decoder->bytespp + 1); - w = RFB_GET_UINT8 (buffer + decoder->bytespp + 2); - h = RFB_GET_UINT8 (buffer + decoder->bytespp + 3); + rfb_decoder_read (decoder, decoder->bytespp + 4); + color = GUINT32_SWAP_LE_BE ((RFB_GET_UINT32 (decoder->data))); + x = RFB_GET_UINT8 (decoder->data + decoder->bytespp); + y = RFB_GET_UINT8 (decoder->data + decoder->bytespp + 1); + w = RFB_GET_UINT8 (decoder->data + decoder->bytespp + 2); + h = RFB_GET_UINT8 (decoder->data + decoder->bytespp + 3); /* draw the rectangle in the foreground */ rfb_decoder_fill_rectangle (decoder, start_x + x, start_y + y, w, h, color); - g_free (buffer); + g_free (decoder->data); + } +} + +static void +rfb_decoder_hextile_encoding (RfbDecoder * decoder, gint start_x, gint start_y, + gint rect_w, gint rect_h) +{ + gint32 x, x_count, x_end, x_max, x_max_16; + gint32 y, y_count, y_end, y_max, y_max_16; + guint8 subencoding, nr_subrect, xy, wh; + guint32 background, foreground; + + x_end = rect_w % 16; + x_count = rect_w / 16 + (x_end > 0 ? 1 : 0); + y_end = rect_h % 16; + y_count = rect_h / 16 + (y_end > 0 ? 1 : 0); + x_max = start_x + rect_w; + y_max = start_y + rect_h; + x_max_16 = x_max - 16; + y_max_16 = y_max - 16; + + for (y = start_y; y < y_max; y += 16) { + for (x = start_x; x < x_max; x += 16) { + + rfb_decoder_read (decoder, 1); + subencoding = RFB_GET_UINT8 (decoder->data); + + if (subencoding & SUBENCODING_RAW) { + rfb_decoder_raw_encoding (decoder, x, y, + (x <= x_max_16 ? 16 : x_end), (y <= y_max_16 ? 16 : y_end)); + continue; + } + + if (subencoding & SUBENCODING_BACKGROUND) { + rfb_decoder_read (decoder, decoder->bytespp); + background = GUINT32_SWAP_LE_BE ((RFB_GET_UINT32 (decoder->data))); + } + rfb_decoder_fill_rectangle (decoder, x, y, + (x <= x_max_16 ? 16 : x_end), (y <= y_max_16 ? 16 : y_end), + background); + + if (subencoding & SUBENCODING_FOREGROUND) { + rfb_decoder_read (decoder, decoder->bytespp); + foreground = GUINT32_SWAP_LE_BE ((RFB_GET_UINT32 (decoder->data))); + } + + if (subencoding & SUBENCODING_ANYSUBRECTS) { + rfb_decoder_read (decoder, 1); + nr_subrect = RFB_GET_UINT8 (decoder->data); + } else { + continue; + } + + if (subencoding & SUBENCODING_SUBRECTSCOLORED) { + guint offset = 0; + + rfb_decoder_read (decoder, nr_subrect * (2 + decoder->bytespp)); + + while (nr_subrect--) { + foreground = + GUINT32_SWAP_LE_BE ((RFB_GET_UINT32 (decoder->data + offset))); + offset += decoder->bytespp; + xy = RFB_GET_UINT8 (decoder->data + offset++); + wh = RFB_GET_UINT8 (decoder->data + offset++); + rfb_decoder_fill_rectangle (decoder, x + (xy >> 4), y + (xy & 0xF), + 1 + (wh >> 4), 1 + (wh & 0xF), foreground); + } + } else { + guint offset = 0; + + rfb_decoder_read (decoder, 2 * nr_subrect); + + while (nr_subrect--) { + xy = RFB_GET_UINT8 (decoder->data + offset++); + wh = RFB_GET_UINT8 (decoder->data + offset++); + rfb_decoder_fill_rectangle (decoder, x + (xy >> 4), y + (xy & 0xF), + 1 + (wh >> 4), 1 + (wh & 0xF), foreground); + } + } + } } } @@ -810,17 +866,15 @@ rfb_decoder_state_set_colour_map_entries (RfbDecoder * decoder) static gboolean rfb_decoder_state_server_cut_text (RfbDecoder * decoder) { - guint8 *buffer; gint cut_text_length; /* 3 bytes padding, 4 bytes cut_text_length */ - buffer = rfb_decoder_read (decoder, 7); - cut_text_length = RFB_GET_UINT32 (buffer + 3); - g_free (buffer); + rfb_decoder_read (decoder, 7); + cut_text_length = RFB_GET_UINT32 (decoder->data + 3); - buffer = rfb_decoder_read (decoder, cut_text_length); - GST_DEBUG ("rfb_decoder_state_server_cut_text: throw away '%s'", buffer); - g_free (buffer); + rfb_decoder_read (decoder, cut_text_length); + GST_DEBUG ("rfb_decoder_state_server_cut_text: throw away '%s'", + decoder->data); decoder->state = rfb_decoder_state_normal; return TRUE; diff --git a/gst/librfb/rfbdecoder.h b/gst/librfb/rfbdecoder.h index 314504ad..c9fb5f55 100644 --- a/gst/librfb/rfbdecoder.h +++ b/gst/librfb/rfbdecoder.h @@ -21,6 +21,13 @@ G_BEGIN_DECLS enum #define ENCODING_TYPE_COPYRECT 1 #define ENCODING_TYPE_RRE 2 #define ENCODING_TYPE_CORRE 4 +#define ENCODING_TYPE_HEXTILE 5 + +#define SUBENCODING_RAW 1 +#define SUBENCODING_BACKGROUND 2 +#define SUBENCODING_FOREGROUND 4 +#define SUBENCODING_ANYSUBRECTS 8 +#define SUBENCODING_SUBRECTSCOLORED 16 typedef struct _RfbDecoder RfbDecoder; @@ -33,6 +40,8 @@ struct _RfbDecoder gint fd; + guint8 *data; + guint32 data_len; gpointer decoder_private; guint8 *frame; guint8 *prev_frame; -- cgit v1.2.1