#include <rfb/JpegEncoder.h>
#include <rdr/OutStream.h>
+#include <rdr/Exception.h>
#include <rfb/encodings.h>
+#include <rfb/ConnParams.h>
#include <rfb/LogWriter.h>
#ifdef HAVE_DMEDIA
jcomp->setQuality(qualityMap[level]);
}
-bool JpegEncoder::writeRect(PixelBuffer* pb, const Rect& r)
+bool JpegEncoder::isPixelFormatSupported(PixelBuffer* pb) const
{
- int serverBitsPerPixel = pb->getPF().bpp;
- int clientBitsPerPixel = writer->bpp();
-
- // FIXME: Implement JPEG compression for (serverBitsPerPixel == 16).
- // FIXME: Check that all color components are actually 8 bits wide.
- if (serverBitsPerPixel != 32 || clientBitsPerPixel < 16) {
- // FIXME: Make sure this return value is checked properly.
- return false;
+ const PixelFormat &serverPF = pb->getPF();
+ const PixelFormat &clientPF = writer->getConnParams()->pf();
+
+ // FIXME: Ask encoders if they support given pixel formats.
+
+ if ( serverPF.bpp == 32 && clientPF.bpp >= 16 &&
+ serverPF.depth == 24 && serverPF.redMax == 255 &&
+ serverPF.greenMax == 255 && serverPF.blueMax == 255 ) {
+ return true;
+ }
+
+ return false;
+}
+
+void JpegEncoder::writeRect(PixelBuffer* pb, const Rect& r)
+{
+ if (!isPixelFormatSupported(pb)) {
+ vlog.error("pixel format unsupported by JPEG encoder");
+ throw rdr::Exception("internal error in JpegEncoder");
}
writer->startRect(r, encodingTight);
os->writeBytes(jcomp->getDataPtr(), jcomp->getDataLength());
writer->endRect();
-
- return true;
}
virtual ~JpegEncoder();
virtual void setQualityLevel(int level);
- virtual bool writeRect(PixelBuffer* pb, const Rect& r);
+ virtual bool isPixelFormatSupported(PixelBuffer* pb) const;
+ virtual void writeRect(PixelBuffer* pb, const Rect& r);
static BoolParameter useHardwareJPEG;
return encoders[encoding]->writeRect(r, ig, actual);
}
-void SMsgWriter::writeVideoRect(PixelBuffer *pb, const Rect& r)
+bool SMsgWriter::canUseJpegEncoder(PixelBuffer *pb) const
+{
+ return jpegEncoder->isPixelFormatSupported(pb);
+}
+
+void SMsgWriter::writeJpegRect(PixelBuffer *pb, const Rect& r)
{
jpegEncoder->writeRect(pb, r);
}
virtual void writeCopyRect(const Rect& r, int srcX, int srcY);
- virtual void writeVideoRect(PixelBuffer *pb, const Rect& r);
+ virtual bool canUseJpegEncoder(PixelBuffer *pb) const;
+ virtual void writeJpegRect(PixelBuffer *pb, const Rect& r);
virtual void startRect(const Rect& r, unsigned int enc)=0;
virtual void endRect()=0;
// complicated as compared to the original VNC4.
writer()->setupCurrentEncoder();
int nRects = (ui.copied.numRects() +
- (ui.video_area.is_empty() ? 0 : 1) +
(drawRenderedCursor ? 1 : 0));
+ if (!ui.video_area.is_empty()) {
+ if (writer()->canUseJpegEncoder(server->getPixelBuffer())) {
+ nRects++;
+ } else {
+ nRects += writer()->getNumRects(ui.video_area);
+ }
+ }
+
std::vector<Rect> rects;
std::vector<Rect>::const_iterator i;
ui.changed.get_rects(&rects);
}
writer()->writeFramebufferUpdateStart(nRects);
- if (!ui.video_area.is_empty())
- writer()->writeVideoRect(server->getPixelBuffer(), ui.video_area);
+ if (!ui.video_area.is_empty()) {
+ if (writer()->canUseJpegEncoder(server->getPixelBuffer())) {
+ writer()->writeJpegRect(server->getPixelBuffer(), ui.video_area);
+ } else {
+ Rect actual;
+ writer()->writeRect(ui.video_area, &image_getter, &actual);
+ }
+ }
Region updatedRegion;
writer()->writeRects(ui, &image_getter, &updatedRegion);
updates.subtract(updatedRegion);