GUACAMOLE-632: Merge dynamic JPEG/WebP quality scaling.
diff --git a/src/common/surface.c b/src/common/surface.c
index 8c690b7..c31dfbf 100644
--- a/src/common/surface.c
+++ b/src/common/surface.c
@@ -79,13 +79,6 @@
#endif
/**
- * The JPEG image quality ('quantization') setting to use. Range 0-100 where
- * 100 is the highest quality/largest file size, and 0 is the lowest
- * quality/smallest file size.
- */
-#define GUAC_SURFACE_JPEG_IMAGE_QUALITY 90
-
-/**
* The framerate which, if exceeded, indicates that JPEG is preferred.
*/
#define GUAC_COMMON_SURFACE_JPEG_FRAMERATE 3
@@ -97,13 +90,6 @@
#define GUAC_SURFACE_JPEG_MIN_BITMAP_SIZE 4096
/**
- * The WebP image quality ('quantization') setting to use. Range 0-100 where
- * 100 is the highest quality/largest file size, and 0 is the lowest
- * quality/smallest file size.
- */
-#define GUAC_SURFACE_WEBP_IMAGE_QUALITY 90
-
-/**
* The JPEG compression min block size. This defines the optimal rectangle block
* size factor for JPEG compression. Usually 8x8 would suffice, but use 16 to
* reduce the occurrence of ringing artifacts further.
@@ -1667,6 +1653,36 @@
}
/**
+ * Returns an appropriate quality between 0 and 100 for lossy encoding
+ * depending on the current processing lag calculated for the given client.
+ *
+ * @param client
+ * The client for which the lossy quality is being calculated.
+ *
+ * @return
+ * A value between 0 and 100 inclusive which seems appropriate for the
+ * client based on lag measurements.
+ */
+static int guac_common_surface_suggest_quality(guac_client* client) {
+
+ int lag = guac_client_get_processing_lag(client);
+
+ /* Scale quality linearly from 90 to 30 as lag varies from 20ms to 80ms */
+ int quality = 90 - (lag - 20);
+
+ /* Do not exceed 90 for quality */
+ if (quality > 90)
+ return 90;
+
+ /* Do not go below 30 for quality */
+ if (quality < 30)
+ return 30;
+
+ return quality;
+
+}
+
+/**
* Flushes the bitmap update currently described by the dirty rectangle within
* the given surface directly via an "img" instruction as JPEG data. The
* resulting instructions will be sent over the socket associated with the
@@ -1702,7 +1718,7 @@
/* Send JPEG for rect */
guac_client_stream_jpeg(surface->client, socket, GUAC_COMP_OVER, layer,
surface->dirty_rect.x, surface->dirty_rect.y, rect,
- GUAC_SURFACE_JPEG_IMAGE_QUALITY);
+ guac_common_surface_suggest_quality(surface->client));
cairo_surface_destroy(rect);
surface->realized = 1;
@@ -1764,7 +1780,7 @@
/* Send WebP for rect */
guac_client_stream_webp(surface->client, socket, GUAC_COMP_OVER, layer,
surface->dirty_rect.x, surface->dirty_rect.y, rect,
- GUAC_SURFACE_WEBP_IMAGE_QUALITY, 0);
+ guac_common_surface_suggest_quality(surface->client), 0);
cairo_surface_destroy(rect);
surface->realized = 1;