gst/librfb/: Add Hextile encoding
authorThijs Vermeir <thijsvermeir@gmail.com>
Wed, 5 Nov 2008 22:25:25 +0000 (22:25 +0000)
committerThijs Vermeir <thijsvermeir@gmail.com>
Wed, 5 Nov 2008 22:25:25 +0000 (22:25 +0000)
Original commit message from CVS:
* gst/librfb/gstrfbsrc.c:
* gst/librfb/rfbdecoder.c:
* gst/librfb/rfbdecoder.h:
Add Hextile encoding

ChangeLog
gst/librfb/gstrfbsrc.c
gst/librfb/rfbdecoder.c
gst/librfb/rfbdecoder.h

index e07adaf..ee2b8b3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2008-11-05  Thijs Vermeir  <thijsvermeir@gmail.com>
+
+       * gst/librfb/gstrfbsrc.c:
+       * gst/librfb/rfbdecoder.c:
+       * gst/librfb/rfbdecoder.h:
+       Add Hextile encoding
+
 2008-11-05  Zaheer Abbas Merali  <zaheerabbas at merali dot org>
 
        patch by: Josep Torra
index fdb0362..0fd62c9 100644 (file)
@@ -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;
index d16e584..4e32cc6 100644 (file)
@@ -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;
@@ -441,6 +429,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 =
       g_slist_append (encoder_list, GUINT_TO_POINTER (ENCODING_TYPE_RRE));
@@ -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;
index 314504a..c9fb5f5 100644 (file)
@@ -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;