The vnc implementation only sends frames when it detects changes in
the server's framebuffer. This leads to artifacts when there are no
further changes, as the internal H264 encoder may still contain data.

This patch modifies the code to send a few additional frames in such
situations to flush the H264 encoder data.

Signed-off-by: Dietmar Maurer <diet...@proxmox.com>
---
 ui/vnc.c | 13 ++++++++++++-
 ui/vnc.h |  3 +++
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/ui/vnc.c b/ui/vnc.c
index ba71589c6f..975f3325e1 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -3234,6 +3234,7 @@ static void vnc_refresh(DisplayChangeListener *dcl)
     VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
     VncState *vs, *vn;
     int has_dirty, rects = 0;
+    bool keep_dirty = false;
 
     if (QTAILQ_EMPTY(&vd->clients)) {
         update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_MAX);
@@ -3251,11 +3252,21 @@ static void vnc_refresh(DisplayChangeListener *dcl)
     vnc_unlock_display(vd);
 
     QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) {
+#ifdef CONFIG_GSTREAMER
+        if (vs->h264) {
+            if (has_dirty) {
+                vs->h264->keep_dirty = VNC_H264_KEEP_DIRTY;
+            } else if (vs->h264->keep_dirty > 0) {
+                keep_dirty = true;
+                vs->h264->keep_dirty--;
+            }
+        }
+#endif
         rects += vnc_update_client(vs, has_dirty);
         /* vs might be free()ed here */
     }
 
-    if (has_dirty && rects) {
+    if ((has_dirty && rects) || keep_dirty) {
         vd->dcl.update_interval /= 2;
         if (vd->dcl.update_interval < VNC_REFRESH_INTERVAL_BASE) {
             vd->dcl.update_interval = VNC_REFRESH_INTERVAL_BASE;
diff --git a/ui/vnc.h b/ui/vnc.h
index 0fe9a9ab16..29012b75c7 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -236,10 +236,13 @@ typedef struct VncZywrle {
 } VncZywrle;
 
 #ifdef CONFIG_GSTREAMER
+/* Number of frames we send after the display is clean. */
+#define VNC_H264_KEEP_DIRTY 10
 typedef struct VncH264 {
     GstElement *pipeline, *source, *gst_encoder, *sink, *convert;
     size_t width;
     size_t height;
+    guint keep_dirty;
 } VncH264;
 #endif
 
-- 
2.39.5


Reply via email to