Browse Source

Allow perceptually lossless refresh

Loosen the definition of "lossless" a bit so that we can use high
quality JPEG to refresh damaged parts of the screen. Although this
isn't bit perfect, it is close enough that most users will not be
able to tell the difference.

Level 9 is used rather than level 8 because some monitors have
exaggerated contrast that allows the artefacts from level 8 to be
noticeable.
tags/v1.9.90
Pierre Ossman 5 years ago
parent
commit
beab2b6e4a
4 changed files with 36 additions and 12 deletions
  1. 24
    8
      common/rfb/EncodeManager.cxx
  2. 4
    2
      common/rfb/Encoder.cxx
  3. 6
    1
      common/rfb/Encoder.h
  4. 2
    1
      common/rfb/TightJPEGEncoder.cxx

+ 24
- 8
common/rfb/EncodeManager.cxx View File

@@ -364,6 +364,8 @@ void EncodeManager::prepareEncoders(bool allowLossy)
enum EncoderClass solid, bitmap, bitmapRLE;
enum EncoderClass indexed, indexedRLE, fullColour;

bool allowJPEG;

rdr::S32 preferred;

std::vector<int>::iterator iter;
@@ -371,6 +373,12 @@ void EncodeManager::prepareEncoders(bool allowLossy)
solid = bitmap = bitmapRLE = encoderRaw;
indexed = indexedRLE = fullColour = encoderRaw;

allowJPEG = conn->cp.pf().bpp >= 16;
if (!allowLossy) {
if (encoders[encoderTightJPEG]->losslessQuality == -1)
allowJPEG = false;
}

// Try to respect the client's wishes
preferred = conn->getPreferredEncoding();
switch (preferred) {
@@ -383,8 +391,7 @@ void EncodeManager::prepareEncoders(bool allowLossy)
bitmapRLE = indexedRLE = fullColour = encoderHextile;
break;
case encodingTight:
if (encoders[encoderTightJPEG]->isSupported() &&
(conn->cp.pf().bpp >= 16) && allowLossy)
if (encoders[encoderTightJPEG]->isSupported() && allowJPEG)
fullColour = encoderTightJPEG;
else
fullColour = encoderTight;
@@ -401,8 +408,7 @@ void EncodeManager::prepareEncoders(bool allowLossy)
// Any encoders still unassigned?

if (fullColour == encoderRaw) {
if (encoders[encoderTightJPEG]->isSupported() &&
(conn->cp.pf().bpp >= 16) && allowLossy)
if (encoders[encoderTightJPEG]->isSupported() && allowJPEG)
fullColour = encoderTightJPEG;
else if (encoders[encoderZRLE]->isSupported())
fullColour = encoderZRLE;
@@ -460,9 +466,17 @@ void EncodeManager::prepareEncoders(bool allowLossy)
encoder = encoders[*iter];

encoder->setCompressLevel(conn->cp.compressLevel);
encoder->setQualityLevel(conn->cp.qualityLevel);
encoder->setFineQualityLevel(conn->cp.fineQualityLevel,
conn->cp.subsampling);

if (allowLossy) {
encoder->setQualityLevel(conn->cp.qualityLevel);
encoder->setFineQualityLevel(conn->cp.fineQualityLevel,
conn->cp.subsampling);
} else {
int level = __rfbmax(conn->cp.qualityLevel,
encoder->losslessQuality);
encoder->setQualityLevel(level);
encoder->setFineQualityLevel(-1, subsampleUndefined);
}
}
}

@@ -567,7 +581,9 @@ Encoder *EncodeManager::startRect(const Rect& rect, int type)
encoder = encoders[klass];
conn->writer()->startRect(rect, encoder->encoding);

if (encoder->flags & EncoderLossy)
if ((encoder->flags & EncoderLossy) &&
((encoder->losslessQuality == -1) ||
(encoder->getQualityLevel() < encoder->losslessQuality)))
lossyRegion.assign_union(Region(rect));
else
lossyRegion.assign_subtract(Region(rect));

+ 4
- 2
common/rfb/Encoder.cxx View File

@@ -24,9 +24,11 @@
using namespace rfb;

Encoder::Encoder(SConnection *conn_, int encoding_,
enum EncoderFlags flags_, unsigned int maxPaletteSize_) :
enum EncoderFlags flags_,
unsigned int maxPaletteSize_, int losslessQuality_) :
encoding(encoding_), flags(flags_),
maxPaletteSize(maxPaletteSize_), conn(conn_)
maxPaletteSize(maxPaletteSize_), losslessQuality(losslessQuality_),
conn(conn_)
{
}


+ 6
- 1
common/rfb/Encoder.h View File

@@ -42,7 +42,8 @@ namespace rfb {
class Encoder {
public:
Encoder(SConnection* conn, int encoding,
enum EncoderFlags flags, unsigned int maxPaletteSize=-1);
enum EncoderFlags flags, unsigned int maxPaletteSize=-1,
int losslessQuality=-1);
virtual ~Encoder();

// isSupported() should return a boolean indicating if this encoder
@@ -95,6 +96,10 @@ namespace rfb {
// Maximum size of the palette per rect
const unsigned int maxPaletteSize;

// Minimum level where the quality loss will not be noticed by
// most users (only relevant with EncoderLossy flag)
const int losslessQuality;

protected:
SConnection* conn;
};

+ 2
- 1
common/rfb/TightJPEGEncoder.cxx View File

@@ -64,7 +64,8 @@ static const struct TightJPEGConfiguration conf[10] = {


TightJPEGEncoder::TightJPEGEncoder(SConnection* conn) :
Encoder(conn, encodingTight, (EncoderFlags)(EncoderUseNativePF | EncoderLossy)),
Encoder(conn, encodingTight,
(EncoderFlags)(EncoderUseNativePF | EncoderLossy), -1, 9),
qualityLevel(-1), fineQuality(-1), fineSubsampling(subsampleUndefined)
{
}

Loading…
Cancel
Save