It sends a full update of the screen, in high quality JPEG format, after a 
programmable idle time.
This is disabled by default. Quality can be configured and be truly lossless.
---
    following remarks from Pierre and DRC, this patch is an improved version.

    - fix codingstyle issues
    - shorten  "automatic lossless refresh" -> "automatic refresh"
    - refresh delay parameter is also used as a "enabled" boolean
    - ALR quality selection, including truly lossless (no JPEG) mode
    - manpage update       
    - timer is only started after an actual update was sent

It took me 20 minutes just trying to prove to myself that the "truly lossless" 
mode worked (ie. that it wasn't merely using high quality JPEG). Some people 
clearly have better eyes than I have - anyway, DRC, your users should be happy 
now (but I didn't make "true lossless" the default).

The approach is rather naive and no tracking of the lossy regions is attempted. 
This will be the subject of another patch. I deem the current patch to be 
better than nothing and therefore request it be applied to TigerVNC. (the 
second patch requires time - which I can find - and skill - which I need to 
acquire - so it might not be done immediately).

        common/rfb/ServerCore.cxx       |    8 ++++++++
 common/rfb/ServerCore.h         |    3 ++-
 common/rfb/VNCSConnectionST.cxx |   37 ++++++++++++++++++++++++++++++++++++-
 common/rfb/VNCSConnectionST.h   |    3 +++
 unix/xserver/hw/vnc/Xvnc.man    |   16 ++++++++++++++++
 5 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/common/rfb/ServerCore.cxx b/common/rfb/ServerCore.cxx
index ae2fd24..ab332f5 100644
--- a/common/rfb/ServerCore.cxx
+++ b/common/rfb/ServerCore.cxx
@@ -93,4 +93,12 @@ rfb::BoolParameter rfb::Server::queryConnect
 ("QueryConnect",
  "Prompt the local user to accept or reject incoming connections.",
  false);
+rfb::IntParameter rfb::Server::automaticRefreshDelay
+("AutomaticRefreshDelay",
+ "Delay (in milliseconds) of inactivity after which to refresh framebuffer. 0 
disables.",
+ 0);
+rfb::IntParameter rfb::Server::automaticRefreshQuality
+("AutomaticRefreshQuality",
+ "JPEG Quality (0-9) for automatic refresh. Special value 10 uses 
mathematically lossless compression.",
+ 9);
 
diff --git a/common/rfb/ServerCore.h b/common/rfb/ServerCore.h
index e12a8bc..2f93886 100644
--- a/common/rfb/ServerCore.h
+++ b/common/rfb/ServerCore.h
@@ -38,6 +38,8 @@ namespace rfb {
     static IntParameter maxIdleTime;
     static IntParameter clientWaitTimeMillis;
     static IntParameter compareFB;
+    static IntParameter automaticRefreshDelay;
+    static IntParameter automaticRefreshQuality;
     static BoolParameter protocol3_3;
     static BoolParameter alwaysShared;
     static BoolParameter neverShared;
@@ -47,7 +49,6 @@ namespace rfb {
     static BoolParameter acceptCutText;
     static BoolParameter sendCutText;
     static BoolParameter queryConnect;
-
   };
 
 };
diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx
index deec186..11a6ced 100644
--- a/common/rfb/VNCSConnectionST.cxx
+++ b/common/rfb/VNCSConnectionST.cxx
@@ -74,7 +74,7 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, 
network::Socket *s,
     drawRenderedCursor(false), removeRenderedCursor(false),
     continuousUpdates(false),
     updateTimer(this), pointerEventTime(0),
-    accessRights(AccessDefault), startTime(time(0))
+    accessRights(AccessDefault), startTime(time(0)), refreshTimer(this)
 {
   setStreams(&sock->inStream(), &sock->outStream());
   peerEndpoint.buf = sock->getPeerEndpoint();
@@ -758,6 +758,9 @@ bool VNCSConnectionST::handleTimeout(Timer* t)
       writeFramebufferUpdate();
     else if (t == &congestionTimer)
       updateCongestion();
+       else if (t == &refreshTimer) {
+         automaticLosslessRefresh();
+    }
   } catch (rdr::Exception& e) {
     close(e.str());
   }
@@ -971,6 +974,7 @@ void VNCSConnectionST::writeFramebufferUpdate()
   // bit if things are congested.
   if (isCongested()) {
     updateTimer.start(50);
+    refreshTimer.stop();
     return;
   }
 
@@ -1070,6 +1074,7 @@ void VNCSConnectionST::writeFramebufferUpdate()
   }
 
   if (!ui.is_empty() || writer()->needFakeUpdate() || drawRenderedCursor) {
+    refreshTimer.stop();
     // Compute the number of rectangles. Tight encoder makes the things more
     // complicated as compared to the original VNC4.
     writer()->setupCurrentEncoder();
@@ -1106,6 +1111,9 @@ void VNCSConnectionST::writeFramebufferUpdate()
     writeRTTPing();
 
     requested.clear();
+
+       if (rfb::Server::automaticRefreshDelay > 0)
+      refreshTimer.start(rfb::Server::automaticRefreshDelay);
   }
 
 out:
@@ -1234,3 +1242,30 @@ int VNCSConnectionST::getStatus()
   return 4;
 }
 
+void VNCSConnectionST::automaticLosslessRefresh(void)
+{
+    // Automatic lossless refresh using JPEG Q95, 1X chroma sampling
+    int q = cp.qualityLevel, fq = cp.fineQualityLevel;
+    JPEG_SUBSAMP subsampling = cp.subsampling;
+    bool noJpeg = cp.noJpeg;
+
+    if (Server::automaticRefreshQuality >= 10) {
+      cp.noJpeg = true;
+      cp.qualityLevel = -1;
+    } else {
+      cp.qualityLevel = Server::automaticRefreshQuality;
+      cp.fineQualityLevel = 5 + cp.qualityLevel * 10;
+      cp.subsampling = SUBSAMP_NONE;
+    }
+
+    // Update all the screen (TODO: be smarter)
+    updates.add_changed(Rect(0, 0, cp.width, cp.height));
+    writeFramebufferUpdate();
+    refreshTimer.stop();
+
+    // Reset to previous compression settings
+    cp.qualityLevel = q;
+    cp.fineQualityLevel = fq;
+    cp.subsampling = subsampling;
+    cp.noJpeg = noJpeg;
+}
diff --git a/common/rfb/VNCSConnectionST.h b/common/rfb/VNCSConnectionST.h
index 72dc59c..153409d 100644
--- a/common/rfb/VNCSConnectionST.h
+++ b/common/rfb/VNCSConnectionST.h
@@ -178,6 +178,8 @@ namespace rfb {
     void setDesktopName(const char *name);
     void setSocketTimeouts();
 
+       void automaticLosslessRefresh(void);
+
     network::Socket* sock;
     CharArray peerEndpoint;
 
@@ -207,6 +209,7 @@ namespace rfb {
     Region cuRegion;
 
     Timer updateTimer;
+    Timer refreshTimer;
 
     std::set<rdr::U32> pressedKeys;
 
diff --git a/unix/xserver/hw/vnc/Xvnc.man b/unix/xserver/hw/vnc/Xvnc.man
index 356925d..560e196 100644
--- a/unix/xserver/hw/vnc/Xvnc.man
+++ b/unix/xserver/hw/vnc/Xvnc.man
@@ -223,6 +223,22 @@ where
 is a hexadecimal keysym. For example, to exchange the " and @ symbols you 
would specify the following:
 .IP "" 10
 RemapKeys=0x22<>0x40
+.IP "" 7
+
+.TP
+.B \-AutomaticRefreshDelay \fIdelay
+Enable automatic lossless refresh and set the delay to  
+.I delay
+milliseconds. If no updates have been sent to the client in the past 
+.I delay 
+milliseconds, Xvnc will update the screen with a visually lossless 
+(JPEG quality 9) compression. Special value 0 disables automatic refresh (and 
is the default).
+
+.TP
+.B \-AutomaticRefreshQuality \fIquality
+Override the quality of the automatic updates. Use 0-9 to select JPEG quality 
level,
+use 10 as a special value to denote mathematically lossless compression. This 
option has no effect unless
+.I \-AutomaticRefreshDelay is also specified.
 
 .SH USAGE WITH INETD
 By configuring the \fBinetd\fP(1) service appropriately, Xvnc can be launched
-- 
1.7.9.2

------------------------------------------------------------------------------
Try before you buy = See our experts in action!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-dev2
_______________________________________________
Tigervnc-devel mailing list
Tigervnc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tigervnc-devel

Reply via email to