void ComparingUpdateTracker::compare()
{
- // First of all, exclude video area from both changed and copied regions.
- // We handle video area separately and do not compare it -- we know it's
- // being changed continuously.
- if (!video_area.is_empty()) {
- changed.assign_subtract(video_area);
- copied.assign_subtract(video_area);
- }
-
std::vector<Rect> rects;
std::vector<Rect>::iterator i;
+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/poll.h>
-
-#include <rfb/IrixCLJpegCompressor.h>
-#include <rfb/LogWriter.h>
-
-using namespace rfb;
-
-static LogWriter vlog("IrixCLJpeg");
-
-const int IrixCLJpegCompressor::DEFAULT_QUALITY = 75;
-
-//
-// Constructor and destructor.
-//
-
-IrixCLJpegCompressor::IrixCLJpegCompressor()
- : m_quality(DEFAULT_QUALITY),
- m_clHandleValid(false),
- m_srcBufferSize(0),
- m_dstBufferSize(0),
- m_sourceData(0),
- m_compressedData(0),
- m_compressedLength(0)
-{
- int impactScheme = clQuerySchemeFromName(CL_ALG_VIDEO, "impact");
- if (impactScheme < 0) {
- vlog.error("Warning: No compression scheme named \"impact\"");
- }
-
- vlog.debug("Trying \"impact\" compression scheme (Octane Compression)");
- int r = clOpenCompressor(impactScheme, &m_clHandle);
- if (r == SUCCESS) {
- vlog.debug("Using \"impact\" compression scheme");
- m_clHandleValid = true;
- return;
- }
- vlog.debug("Trying Cosmo Compress");
- r = clOpenCompressor(CL_JPEG_COSMO, &m_clHandle);
- if (r == SUCCESS) {
- vlog.debug("Using Cosmo Compress");
- m_clHandleValid = true;
- return;
- }
-
-#ifdef DEBUG_FORCE_CL
- vlog.debug("DEBUG: Trying Irix software JPEG compressor");
- r = clOpenCompressor(CL_JPEG_SOFTWARE, &m_clHandle);
- if (r == SUCCESS) {
- vlog.debug("DEBUG: Using Irix software JPEG compressor");
- m_clHandleValid = true;
- return;
- }
-#endif
-
- vlog.error("Ho hardware JPEG available via Irix CL library");
-}
-
-IrixCLJpegCompressor::~IrixCLJpegCompressor()
-{
- if (m_clHandleValid)
- clCloseCompressor(m_clHandle);
-
- if (m_sourceData)
- delete[] m_sourceData;
- if (m_compressedData)
- delete[] m_compressedData;
-}
-
-//
-// Set JPEG quality level (1..99)
-//
-
-void
-IrixCLJpegCompressor::setQuality(int level)
-{
- if (level < 1) {
- level = 1;
- } else if (level > 99) {
- level = 99;
- }
- if (level != m_quality) {
- m_quality = level;
- }
-}
-
-//
-// Perform JPEG compression.
-//
-// FIXME: This function assumes that pixel format is 32-bit XBGR
-// (depth 24), compatible with IRIX Compression Library.
-//
-
-void
-IrixCLJpegCompressor::compress(const rdr::U32 *buf,
- const PixelFormat *fmt,
- int w, int h, int stride)
-{
- // Discard previous compression results.
- m_compressedLength = 0;
-
- // A sanity check.
- if (!m_clHandleValid)
- return;
-
- // (Re)allocate the source buffer if necessary.
- if (w * h > m_srcBufferSize) {
- if (m_sourceData)
- delete[] m_sourceData;
- m_srcBufferSize = w * h;
- m_sourceData = new rdr::U32[m_srcBufferSize];
- }
-
- // Copy source pixels
- for (int y = 0; y < h; y++) {
- memcpy(&m_sourceData[y * w], &buf[y * stride], w * sizeof(rdr::U32));
- }
-
- // Set image attributes and JPEG quality factor.
- clSetParam(m_clHandle, CL_FORMAT, CL_FORMAT_XBGR);
- clSetParam(m_clHandle, CL_IMAGE_WIDTH, w);
- clSetParam(m_clHandle, CL_IMAGE_HEIGHT, h);
- clSetParam(m_clHandle, CL_FRAME_BUFFER_SIZE, w * h * 4);
- clSetParam(m_clHandle, CL_JPEG_QUALITY_FACTOR, m_quality);
-
- // Determine buffer size required.
- int newBufferSize = clGetParam(m_clHandle, CL_COMPRESSED_BUFFER_SIZE);
-
- // (Re)allocate destination buffer if necessary.
- if (newBufferSize > m_dstBufferSize) {
- if (m_compressedData)
- delete[] m_compressedData;
- m_dstBufferSize = newBufferSize;
- m_compressedData = new char[m_dstBufferSize];
- }
-
- int newCompressedSize = newBufferSize;
- int n = clCompress(m_clHandle, 1, m_sourceData,
- &newCompressedSize, m_compressedData);
- if (n != 1)
- return;
-
- m_compressedLength = (size_t)newCompressedSize;
-}
-
+++ /dev/null
-#ifndef __IRIXCLJPEGCOMPRESSOR_H__
-#define __IRIXCLJPEGCOMPRESSOR_H__
-
-#include <sys/types.h>
-#include <dmedia/cl.h>
-
-#include <rdr/types.h>
-#include <rfb/PixelFormat.h>
-
-#include <rfb/JpegCompressor.h>
-
-namespace rfb {
-
- //
- // A C++ class for performing JPEG compression.
- // This implementation uses IRIX Compression Library (CL).
- //
-
- class IrixCLJpegCompressor : public JpegCompressor
- {
- public:
- IrixCLJpegCompressor();
- virtual ~IrixCLJpegCompressor();
-
- // Check if the object has been created successfully.
- bool isValid() const { return m_clHandleValid; }
-
- // Set JPEG quality level (0..100).
- virtual void setQuality(int level);
-
- // Actually compress the image.
- virtual void compress(const rdr::U32 *buf, const PixelFormat *fmt,
- int w, int h, int stride);
-
- // Access results of the compression.
- virtual size_t getDataLength() { return m_compressedLength; }
- virtual const char *getDataPtr() { return m_compressedData; }
-
- protected:
- static const int DEFAULT_QUALITY;
- int m_quality;
-
- CLhandle m_clHandle;
- bool m_clHandleValid;
-
- int m_srcBufferSize;
- int m_dstBufferSize;
-
- rdr::U32 *m_sourceData;
- char *m_compressedData;
-
- size_t m_compressedLength;
- };
-
-}
-
-#endif // __IRIXCLJPEGCOMPRESSOR_H__
-
+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/poll.h>
-
-#include <rfb/IrixDMIC_RawToJpeg.h>
-#include <rfb/LogWriter.h>
-
-using namespace rfb;
-
-static LogWriter vlog("IrixDMIC");
-
-//
-// Constructor. Find a converter and create a context. Also, create
-// DMparams structures for using with dmICSetSrcParams,
-// dmICSetDstParams and dmICSetConvParams.
-//
-
-IrixDMIC_RawToJpeg::IrixDMIC_RawToJpeg(bool needRealtime)
- : m_valid_ic(false),
- m_srcParams(0),
- m_dstParams(0),
- m_convParams(0)
-{
- if ( dmParamsCreate(&m_srcParams) != DM_SUCCESS ||
- dmParamsCreate(&m_dstParams) != DM_SUCCESS ||
- dmParamsCreate(&m_convParams) != DM_SUCCESS ) {
- reportError("dmParamsCreate");
- return;
- }
-
- DMparams *p;
- const int JPEG_ID = 0x6A706567; // same as 'jpeg'
- int id, direction, speed;
-
- int n = dmICGetNum();
- while (n--) {
- if (dmParamsCreate(&p) != DM_SUCCESS) {
- reportError("dmParamsCreate");
- return;
- }
- if (dmICGetDescription(n, p) != DM_SUCCESS)
- continue;
- id = dmParamsGetInt(p, DM_IC_ID);
- direction = dmParamsGetEnum(p, DM_IC_CODE_DIRECTION);
- speed = dmParamsGetEnum(p, DM_IC_SPEED);
- if ( id == JPEG_ID && direction == DM_IC_CODE_DIRECTION_ENCODE &&
- (!needRealtime || speed == DM_IC_SPEED_REALTIME) ) {
-
- const char *engine = dmParamsGetString(p, DM_IC_ENGINE);
- vlog.info("Found JPEG encoder: \"%s\" (%d)", engine, n);
-
- dmParamsDestroy(p);
- break;
- }
- dmParamsDestroy(p);
- }
- if (n < 0) {
- vlog.error("Error: No matching JPEG encoder found");
- debugListConverters();
- return;
- }
- if (dmICCreate(n, &m_ic) != DM_SUCCESS) {
- reportError("dmICCreate");
- return;
- }
-
- m_valid_ic = true;
-}
-
-//
-// Destructor.
-//
-
-IrixDMIC_RawToJpeg::~IrixDMIC_RawToJpeg()
-{
- if (m_valid_ic)
- dmICDestroy(m_ic);
-
- if (m_convParams)
- dmParamsDestroy(m_convParams);
- if (m_dstParams)
- dmParamsDestroy(m_dstParams);
- if (m_srcParams)
- dmParamsDestroy(m_srcParams);
-}
-
-void
-IrixDMIC_RawToJpeg::debugListConverters()
-{
- int n = dmICGetNum();
- vlog.debug("IRIX DMIC converters available (%d):", n);
- for (int i = 0; i < n; i++) {
- DMparams *p;
- if (dmParamsCreate(&p) != DM_SUCCESS) {
- return;
- }
- if (dmICGetDescription(i, p) != DM_SUCCESS) {
- vlog.debug(" continue");
- continue;
- }
- union {
- int id;
- char label[5];
- } id;
- id.id = dmParamsGetInt(p, DM_IC_ID);
- id.label[4] = '\0';
- int direction = dmParamsGetEnum(p, DM_IC_CODE_DIRECTION);
- const char *directionLabel = "converter";
- if (direction == DM_IC_CODE_DIRECTION_ENCODE) {
- directionLabel = "encoder";
- } else if (direction == DM_IC_CODE_DIRECTION_DECODE) {
- directionLabel = "decoder";
- }
- int speed = dmParamsGetEnum(p, DM_IC_SPEED);
- const char *speedLabel = "";
- if (speed == DM_IC_SPEED_REALTIME) {
- speedLabel = "realtime ";
- }
- const char *engine = dmParamsGetString(p, DM_IC_ENGINE);
- vlog.debug(" converter %d: '%s' %s%s (%s)",
- i, id.label, speedLabel, directionLabel, engine);
- dmParamsDestroy(p);
- }
-}
-
-//
-// Configure the source and destination formats.
-//
-// FIXME: Remember image size that was previously set, do not set the
-// same size again.
-//
-
-bool
-IrixDMIC_RawToJpeg::setImageParams(int w, int h)
-{
- if (!m_valid_ic) {
- reportErrorNotInited();
- return false;
- }
-
- // Set source image parameters.
- DMpacking packing = DM_IMAGE_PACKING_XBGR;
- int orient = DM_IMAGE_TOP_TO_BOTTOM;
- if (dmSetImageDefaults(m_srcParams, w, h, packing) != DM_SUCCESS) {
- reportError("dmSetImageDefaults");
- return false;
- }
- DMstatus err = dmParamsSetEnum(m_srcParams, DM_IMAGE_ORIENTATION, orient);
- if (err != DM_SUCCESS) {
- reportError("dmParamsSetEnum");
- return false;
- }
- if (dmICSetSrcParams(m_ic, m_srcParams) != DM_SUCCESS) {
- reportError("dmICSetSrcParams");
- return false;
- }
-
- // Set destination image parameters.
- packing = DM_IMAGE_PACKING_CbYCrY;
- const char *compression = DM_IMAGE_JPEG;
- if (dmSetImageDefaults(m_dstParams, w, h, packing) != DM_SUCCESS) {
- reportError("dmSetImageDefaults");
- return false;
- }
- err = dmParamsSetEnum(m_dstParams, DM_IMAGE_ORIENTATION, orient);
- if (err != DM_SUCCESS) {
- reportError("dmParamsSetEnum");
- return false;
- }
- err = dmParamsSetString(m_dstParams, DM_IMAGE_COMPRESSION, compression);
- if (err != DM_SUCCESS) {
- reportError("dmParamsSetString");
- return false;
- }
- if (dmICSetDstParams(m_ic, m_dstParams) != DM_SUCCESS) {
- reportError("dmICSetDstParams");
- return false;
- }
-
- return true;
-}
-
-//
-// Set JPEG image quality level (an integer in the range 0..99).
-//
-// FIXME: Remember image quality that was previously set, do not set
-// the same quality again.
-//
-
-bool
-IrixDMIC_RawToJpeg::setImageQuality(int quality)
-{
- if (!m_valid_ic) {
- reportErrorNotInited();
- return false;
- }
-
- double qf = (double)quality / 100.0;
-
- DMstatus err = dmParamsSetFloat(m_convParams, DM_IMAGE_QUALITY_SPATIAL, qf);
- if (err != DM_SUCCESS) {
- reportError("dmParamsSetFloat");
- return false;
- }
-
- // For some reason, dmICSetConvParams() does not have effect without
- // calling dmICSetDstParams() as well. So we call it here.
- if (m_dstParams && dmParamsGetNumElems(m_dstParams) &&
- dmICSetDstParams(m_ic, m_dstParams) != DM_SUCCESS) {
- reportError("dmICSetDstParams");
- return false;
- }
-
- if (dmICSetConvParams(m_ic, m_convParams) != DM_SUCCESS) {
- reportError("dmICSetConvParams");
- return false;
- }
-
- return true;
-}
-
-//
-// Set up source buffer pool.
-//
-// NOTE: Both setImageParams() and setImageQuality() functions should
-// be called prior to creating and registering buffer pools.
-//
-
-bool
-IrixDMIC_RawToJpeg::createSrcBufferPool(DMbufferpool *pool,
- int bufCount, int bufSize)
-{
- if (!m_valid_ic) {
- reportErrorNotInited();
- return false;
- }
-
- DMparams *p;
- if (dmParamsCreate(&p) != DM_SUCCESS) {
- reportError("dmParamsCreate");
- return false;
- }
-
- if (dmBufferSetPoolDefaults(p, bufCount, bufSize, DM_FALSE, DM_TRUE) !=
- DM_SUCCESS) {
- reportError("dmBufferSetPoolDefaults");
- dmParamsDestroy(p);
- return false;
- }
- if (dmICGetSrcPoolParams(m_ic, p) != DM_SUCCESS) {
- reportError("dmICGetSrcPoolParams");
- dmParamsDestroy(p);
- return false;
- }
- if (dmBufferCreatePool(p, pool) != DM_SUCCESS) {
- reportError("dmBufferCreatePool");
- dmParamsDestroy(p);
- return false;
- }
-
- dmParamsDestroy(p);
- return true;
-}
-
-//
-// Set up and register destination buffer pool.
-//
-// NOTE: Both setImageParams() and setImageQuality() functions should
-// be called prior to creating and registering buffer pools.
-//
-
-bool
-IrixDMIC_RawToJpeg::registerDstBufferPool(DMbufferpool *pool,
- int bufCount, int bufSize)
-{
- if (!m_valid_ic) {
- reportErrorNotInited();
- return false;
- }
-
- DMparams *p;
- if (dmParamsCreate(&p) != DM_SUCCESS) {
- reportError("dmParamsCreate");
- return false;
- }
-
- if (dmBufferSetPoolDefaults(p, bufCount, bufSize, DM_FALSE, DM_TRUE) !=
- DM_SUCCESS) {
- reportError("dmBufferSetPoolDefaults");
- dmParamsDestroy(p);
- return false;
- }
- if (dmICGetDstPoolParams(m_ic, p) != DM_SUCCESS) {
- reportError("dmICGetDstPoolParams");
- dmParamsDestroy(p);
- return false;
- }
- if (dmBufferCreatePool(p, pool) != DM_SUCCESS) {
- reportError("dmBufferCreatePool");
- dmParamsDestroy(p);
- return false;
- }
-
- dmParamsDestroy(p);
-
- if (dmICSetDstPool(m_ic, *pool) != DM_SUCCESS) {
- reportError("dmICSetDstPool");
- destroyBufferPool(*pool);
- return false;
- }
-
- return true;
-}
-
-//
-// Destroy buffer pool created with either createSrcBufferPool() or
-// registerDstBufferPool().
-//
-
-void
-IrixDMIC_RawToJpeg::destroyBufferPool(DMbufferpool pool)
-{
- if (dmBufferDestroyPool(pool) != DM_SUCCESS)
- reportError("dmBufferDestroyPool");
-}
-
-//
-// Allocate a buffer from the specified pool.
-//
-
-bool
-IrixDMIC_RawToJpeg::allocBuffer(DMbuffer *pbuf, DMbufferpool pool)
-{
- if (dmBufferAllocate(pool, pbuf) != DM_SUCCESS) {
- reportError("dmBufferAllocate");
- return false;
- }
-
- return true;
-}
-
-//
-// Fill in a DMbuffer with data.
-//
-// NOTE: The caller must make sure that the buffer size is no less
-// than dataSize.
-//
-
-bool
-IrixDMIC_RawToJpeg::copyToBuffer(DMbuffer buf, const void *data, int dataSize)
-{
- void *bufPtr = dmBufferMapData(buf);
- memcpy(bufPtr, data, dataSize);
-
- if (dmBufferSetSize(buf, dataSize) != DM_SUCCESS) {
- reportError("dmBufferSetSize");
- return false;
- }
-
- return true;
-}
-
-//
-// Fill in a DMbuffer with data.
-//
-// NOTE: The caller must make sure that the buffer size is no less
-// than (nRows * rowSize).
-//
-
-bool
-IrixDMIC_RawToJpeg::copyToBuffer(DMbuffer buf, const void *data,
- int rowSize, int nRows, int stride)
-{
- char *dataBytes = (char *)data;
- char *bufPtr = (char *)dmBufferMapData(buf);
- for (int i = 0; i < nRows; i++) {
- memcpy(bufPtr, &dataBytes[i * stride], rowSize);
- bufPtr += rowSize;
- }
-
- if (dmBufferSetSize(buf, nRows * rowSize) != DM_SUCCESS) {
- reportError("dmBufferSetSize");
- return false;
- }
-
- return true;
-}
-
-//
-// Map DMbuffer to physical memory.
-//
-
-void *
-IrixDMIC_RawToJpeg::mapBufferData(DMbuffer buf)
-{
- return dmBufferMapData(buf);
-}
-
-//
-// Get the number of valid bytes in DMbuffer.
-//
-
-int
-IrixDMIC_RawToJpeg::getBufferSize(DMbuffer buf)
-{
- return dmBufferGetSize(buf);
-}
-
-//
-// Free DMbuffer.
-//
-
-void
-IrixDMIC_RawToJpeg::freeBuffer(DMbuffer buf)
-{
- if (dmBufferFree(buf) != DM_SUCCESS)
- reportError("dmBufferFree");
-}
-
-//
-// Send input data (raw pixels) to the converter.
-//
-
-bool
-IrixDMIC_RawToJpeg::sendData(DMbuffer buf)
-{
- if (dmICSend(m_ic, buf, 0, NULL) != DM_SUCCESS) {
- reportError("dmICSend");
- return false;
- }
-
- return true;
-}
-
-//
-// Wait until compression is finished (infinite timeout!).
-// This function should be called after sendData() and before receiveData().
-//
-// FIXME: Report errors.
-//
-
-bool
-IrixDMIC_RawToJpeg::waitConversion()
-{
- struct pollfd ps;
- ps.fd = dmICGetDstQueueFD(m_ic);
- ps.events = POLLIN;
-
- int result = poll(&ps, 1, -1);
- if (result != 1)
- return false;
-
- if ((ps.revents & POLLIN) != 0) {
- return true;
- } else {
- return false;
- }
-}
-
-//
-// Receive output (JPEG data) from the converter.
-// Call waitConversion() function first.
-//
-
-bool
-IrixDMIC_RawToJpeg::receiveData(DMbuffer *pbuf)
-{
- if (dmICReceive(m_ic, pbuf) != DM_SUCCESS) {
- reportError("dmICReceive");
- return false;
- }
-
- return true;
-}
-
-//
-// Report an error when a function returns DM_FAILURE.
-//
-
-void
-IrixDMIC_RawToJpeg::reportError(const char *funcName)
-{
- char errorDetail[DM_MAX_ERROR_DETAIL];
- const char *errorCategory = dmGetError(NULL, errorDetail);
- vlog.error("%s() failed: %s: %s",
- funcName, errorCategory, errorDetail);
-}
-
-//
-// Report an error when (m_valid_ic == false).
-//
-
-void
-IrixDMIC_RawToJpeg::reportErrorNotInited()
-{
- vlog.error("Internal error: Image converter not initialized");
-}
-
+++ /dev/null
-#ifndef __IRIXDMIC_RAWTOJPEG_H__
-#define __IRIXDMIC_RAWTOJPEG_H__
-
-#include <dmedia/dmedia.h>
-#include <dmedia/dm_imageconvert.h>
-
-namespace rfb {
-
- //
- // A C++ wrapper for IRIX-specific Digital Media Image Conversion
- // library used for JPEG compression.
- //
-
- class IrixDMIC_RawToJpeg
- {
- public:
- IrixDMIC_RawToJpeg(bool needRealtime = true);
- virtual ~IrixDMIC_RawToJpeg();
-
- void debugListConverters();
-
- bool isValid() const { return m_valid_ic; }
-
- bool setImageParams(int w, int h);
- bool setImageQuality(int quality);
-
- bool createSrcBufferPool(DMbufferpool *pool, int bufCount, int bufSize);
- bool registerDstBufferPool(DMbufferpool *pool, int bufCount, int bufSize);
- static void destroyBufferPool(DMbufferpool pool);
-
- static bool allocBuffer(DMbuffer *pbuf, DMbufferpool pool);
- static bool copyToBuffer(DMbuffer buf, const void *data, int dataSize);
- static bool copyToBuffer(DMbuffer buf, const void *data,
- int rowSize, int nRows, int stride);
- static int getBufferSize(DMbuffer buf);
- static void * mapBufferData(DMbuffer buf);
- static void freeBuffer(DMbuffer buf);
-
- bool sendData(DMbuffer buf);
- bool waitConversion();
- bool receiveData(DMbuffer *pbuf);
-
- static void reportError(const char *funcName);
- static void reportErrorNotInited();
-
- protected:
- DMimageconverter m_ic;
- bool m_valid_ic;
-
- DMparams *m_srcParams;
- DMparams *m_dstParams;
- DMparams *m_convParams;
- };
-
-}
-
-#endif // __IRIXDMIC_RAWTOJPEG_H__
-
+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/poll.h>
-
-#include <rfb/IrixDMJpegCompressor.h>
-
-using namespace rfb;
-
-const int IrixDMJpegCompressor::DEFAULT_QUALITY = 75;
-
-//
-// Constructor and destructor.
-//
-
-IrixDMJpegCompressor::IrixDMJpegCompressor()
- : m_quality(DEFAULT_QUALITY),
- m_width(0),
- m_height(0),
- m_bufferSize(0),
- m_compressedData(0),
- m_compressedLength(0)
-{
-}
-
-IrixDMJpegCompressor::~IrixDMJpegCompressor()
-{
- if (m_bufferSize > 0) {
- m_ic.destroyBufferPool(m_srcPool);
- m_ic.destroyBufferPool(m_dstPool);
- }
-
- if (m_compressedData)
- delete[] m_compressedData;
-}
-
-//
-// Set JPEG quality level (1..99)
-//
-
-void
-IrixDMJpegCompressor::setQuality(int level)
-{
- if (level < 1) {
- level = 1;
- } else if (level > 99) {
- level = 99;
- }
- if (level != m_quality) {
- m_quality = level;
- m_ic.setImageQuality(level);
- }
-}
-
-//
-// Perform JPEG compression.
-//
-// FIXME: This function assumes that pixel format is 32-bit XBGR
-// (depth 24), compatible with IRIX Digital Media libraries.
-//
-
-void
-IrixDMJpegCompressor::compress(const rdr::U32 *buf,
- const PixelFormat *fmt,
- int w, int h, int stride)
-{
- // Discard previous compression results.
- if (m_compressedData) {
- delete[] m_compressedData;
- m_compressedData = 0;
- }
- m_compressedLength = 0;
-
- // Setup the compressor.
- if (!updateImageSize(w, h))
- return;
-
- // Prepare source image data.
- DMbuffer srcBuf;
- if (!m_ic.allocBuffer(&srcBuf, m_srcPool)) {
- return;
- }
- int widthInBytes = w * (fmt->bpp / 8);
- int strideInBytes = stride * (fmt->bpp / 8);
- if (!m_ic.copyToBuffer(srcBuf, buf, widthInBytes, h, strideInBytes)) {
- m_ic.freeBuffer(srcBuf);
- return;
- }
-
- // Initiate compression.
- if (!m_ic.sendData(srcBuf)) {
- m_ic.freeBuffer(srcBuf);
- return;
- }
- m_ic.freeBuffer(srcBuf);
-
- // Wait for results.
- if (!m_ic.waitConversion()) {
- perror("poll"); // FIXME: Unify error handling.
- return;
- }
-
- // Save the results.
- DMbuffer dstBuf;
- if (!m_ic.receiveData(&dstBuf)) {
- return;
- }
- m_compressedLength = m_ic.getBufferSize(dstBuf);
- m_compressedData = new char[m_compressedLength];
- void *bufPtr = m_ic.mapBufferData(dstBuf);
- memcpy(m_compressedData, bufPtr, m_compressedLength);
-
- m_ic.freeBuffer(dstBuf);
-}
-
-//
-// Update image size and make sure that our buffer pools will allocate
-// properly-sized buffers.
-//
-// FIXME: Handle image quality separately.
-//
-
-bool
-IrixDMJpegCompressor::updateImageSize(int w, int h)
-{
- // Configure image formats and parameters, set JPEG image quality level.
- if (w != m_width || h != m_height) {
- if (!m_ic.setImageParams(w, h) || !m_ic.setImageQuality(m_quality)) {
- return false;
- }
- m_width = w;
- m_height = h;
- }
-
- // Set up source and destination buffer pools.
- int dataLen = w * h * 4;
- if (dataLen > m_bufferSize) {
- if (m_bufferSize > 0) {
- m_ic.destroyBufferPool(m_srcPool);
- m_ic.destroyBufferPool(m_dstPool);
- m_bufferSize = 0;
- }
- if (!m_ic.createSrcBufferPool(&m_srcPool, 1, dataLen)) {
- return false;
- }
- if (!m_ic.registerDstBufferPool(&m_dstPool, 1, dataLen)) {
- m_ic.destroyBufferPool(m_srcPool);
- return false;
- }
- m_bufferSize = dataLen;
- }
-
- return true;
-}
-
+++ /dev/null
-#ifndef __IRIXDMJPEGCOMPRESSOR_H__
-#define __IRIXDMJPEGCOMPRESSOR_H__
-
-#include <sys/types.h>
-
-#include <rdr/types.h>
-#include <rfb/PixelFormat.h>
-
-#include <rfb/JpegCompressor.h>
-#include <rfb/IrixDMIC_RawToJpeg.h>
-
-namespace rfb {
-
- //
- // A C++ class for performing JPEG compression.
- // This implementation uses IRIX Digital Media libraries.
- //
-
- class IrixDMJpegCompressor : public JpegCompressor
- {
- public:
- IrixDMJpegCompressor();
- virtual ~IrixDMJpegCompressor();
-
- // Check if the object has been created successfully.
- bool isValid() const { return m_ic.isValid(); }
-
- // Set JPEG quality level (0..100).
- virtual void setQuality(int level);
-
- // Actually compress the image.
- virtual void compress(const rdr::U32 *buf, const PixelFormat *fmt,
- int w, int h, int stride);
-
- // Access results of the compression.
- virtual size_t getDataLength() { return m_compressedLength; }
- virtual const char *getDataPtr() { return m_compressedData; }
-
- protected:
- // Update image size and make sure that our buffer pools will
- // allocate properly-sized buffers.
- bool updateImageSize(int w, int h);
-
- protected:
- static const int DEFAULT_QUALITY;
- int m_quality;
-
- IrixDMIC_RawToJpeg m_ic;
- int m_width;
- int m_height;
- DMbufferpool m_srcPool;
- DMbufferpool m_dstPool;
- int m_bufferSize;
-
- char *m_compressedData;
- size_t m_compressedLength;
- };
-
-}
-
-#endif // __IRIXDMJPEGCOMPRESSOR_H__
-
+++ /dev/null
-#include <stdlib.h>
-
-#include <rfb/JpegCompressor.h>
-
-using namespace rfb;
-
-const int StandardJpegCompressor::ALLOC_CHUNK_SIZE = 65536;
-const int StandardJpegCompressor::DEFAULT_QUALITY = 75;
-
-//
-// Extend jpeg_destination_mgr struct with a pointer to our object.
-//
-
-typedef struct {
- struct jpeg_destination_mgr pub;
- StandardJpegCompressor *_this;
-} my_destination_mgr;
-
-//
-// C-compatible interface to our destination manager. It just obtains
-// a pointer to the right object and calls a corresponding C++ member
-// function on that object.
-//
-
-static void
-init_destination(j_compress_ptr cinfo)
-{
- my_destination_mgr *dest_ptr = (my_destination_mgr *)cinfo->dest;
- dest_ptr->_this->initDestination();
-}
-
-static boolean
-empty_output_buffer (j_compress_ptr cinfo)
-{
- my_destination_mgr *dest_ptr = (my_destination_mgr *)cinfo->dest;
- return (boolean)dest_ptr->_this->emptyOutputBuffer();
-}
-
-static void
-term_destination (j_compress_ptr cinfo)
-{
- my_destination_mgr *dest_ptr = (my_destination_mgr *)cinfo->dest;
- dest_ptr->_this->termDestination();
-}
-
-//
-// Constructor and destructor.
-//
-
-StandardJpegCompressor::StandardJpegCompressor()
- : m_cdata(0),
- m_cdata_allocated(0),
- m_cdata_ready(0)
-{
- // Initialize JPEG compression structure.
- m_cinfo.err = jpeg_std_error(&m_jerr);
- jpeg_create_compress(&m_cinfo);
-
- // Set up a destination manager.
- my_destination_mgr *dest = new my_destination_mgr;
- dest->pub.init_destination = init_destination;
- dest->pub.empty_output_buffer = empty_output_buffer;
- dest->pub.term_destination = term_destination;
- dest->_this = this;
- m_cinfo.dest = (jpeg_destination_mgr *)dest;
-
- // Set up a destination manager.
- m_cinfo.input_components = 3;
- m_cinfo.in_color_space = JCS_RGB;
- jpeg_set_defaults(&m_cinfo);
- jpeg_set_quality(&m_cinfo, DEFAULT_QUALITY, true);
-
- // We prefer speed over quality.
- m_cinfo.dct_method = JDCT_FASTEST;
-}
-
-StandardJpegCompressor::~StandardJpegCompressor()
-{
- // Free compressed data buffer.
- if (m_cdata)
- free(m_cdata);
-
- // Clean up the destination manager.
- delete m_cinfo.dest;
- m_cinfo.dest = NULL;
-
- // Release the JPEG compression structure.
- jpeg_destroy_compress(&m_cinfo);
-}
-
-//
-// Our implementation of destination manager.
-//
-
-void
-StandardJpegCompressor::initDestination()
-{
- if (!m_cdata) {
- size_t new_size = ALLOC_CHUNK_SIZE;
- m_cdata = (unsigned char *)malloc(new_size);
- m_cdata_allocated = new_size;
- }
-
- m_cdata_ready = 0;
- m_cinfo.dest->next_output_byte = m_cdata;
- m_cinfo.dest->free_in_buffer = m_cdata_allocated;
-}
-
-bool
-StandardJpegCompressor::emptyOutputBuffer()
-{
- size_t old_size = m_cdata_allocated;
- size_t new_size = old_size + ALLOC_CHUNK_SIZE;
-
- m_cdata = (unsigned char *)realloc(m_cdata, new_size);
- m_cdata_allocated = new_size;
-
- m_cinfo.dest->next_output_byte = &m_cdata[old_size];
- m_cinfo.dest->free_in_buffer = new_size - old_size;
-
- return true;
-}
-
-void
-StandardJpegCompressor::termDestination()
-{
- m_cdata_ready = m_cdata_allocated - m_cinfo.dest->free_in_buffer;
-}
-
-//
-// Set JPEG quality level (0..100)
-//
-
-void
-StandardJpegCompressor::setQuality(int level)
-{
- if (level < 0) {
- level = 0;
- } else if (level > 100) {
- level = 100;
- }
- jpeg_set_quality(&m_cinfo, level, true);
-}
-
-//
-// Perform JPEG compression.
-//
-// FIXME: This function assumes that (fmt->bpp == 32 &&
-// fmt->depth == 24 && fmt->redMax == 255 &&
-// fmt->greenMax == 255 && fmt->blueMax == 255).
-//
-
-void
-StandardJpegCompressor::compress(const rdr::U32 *buf,
- const PixelFormat *fmt,
- int w, int h, int stride)
-{
- m_cinfo.image_width = w;
- m_cinfo.image_height = h;
-
- jpeg_start_compress(&m_cinfo, TRUE);
-
- const rdr::U32 *src = buf;
-
- // We'll pass up to 8 rows to jpeg_write_scanlines().
- JSAMPLE *rgb = new JSAMPLE[w * 3 * 8];
- JSAMPROW row_pointer[8];
- for (int i = 0; i < 8; i++)
- row_pointer[i] = &rgb[w * 3 * i];
-
- // Feed the pixels to the JPEG library.
- while (m_cinfo.next_scanline < m_cinfo.image_height) {
- int max_rows = m_cinfo.image_height - m_cinfo.next_scanline;
- if (max_rows > 8) {
- max_rows = 8;
- }
- for (int dy = 0; dy < max_rows; dy++) {
- JSAMPLE *dst = row_pointer[dy];
- for (int x = 0; x < w; x++) {
- dst[x*3] = (JSAMPLE)(src[x] >> fmt->redShift);
- dst[x*3+1] = (JSAMPLE)(src[x] >> fmt->greenShift);
- dst[x*3+2] = (JSAMPLE)(src[x] >> fmt->blueShift);
- }
- src += stride;
- }
- jpeg_write_scanlines(&m_cinfo, row_pointer, max_rows);
- }
-
- delete[] rgb;
-
- jpeg_finish_compress(&m_cinfo);
-}
-
+++ /dev/null
-#ifndef __JPEGCOMPRESSOR_H__
-#define __JPEGCOMPRESSOR_H__
-
-#include <stdio.h>
-#include <sys/types.h>
-extern "C" {
-#include <jpeglib.h>
-}
-
-#include <rdr/types.h>
-#include <rfb/PixelFormat.h>
-
-namespace rfb {
-
- //
- // An abstract interface for performing JPEG compression.
- //
-
- class JpegCompressor
- {
- public:
- virtual ~JpegCompressor() {}
-
- // Set JPEG quality level (0..100)
- virtual void setQuality(int level) = 0;
-
- // Actually compress an image.
- virtual void compress(const rdr::U32 *buf, const PixelFormat *fmt,
- int w, int h, int stride) = 0;
-
- // Access results of the compression.
- virtual size_t getDataLength() = 0;
- virtual const char *getDataPtr() = 0;
- };
-
- //
- // A C++ class for performing JPEG compression via the
- // Independent JPEG Group's software (free JPEG library).
- //
-
- class StandardJpegCompressor : public JpegCompressor
- {
- public:
- StandardJpegCompressor();
- virtual ~StandardJpegCompressor();
-
- // Set JPEG quality level (0..100)
- virtual void setQuality(int level);
-
- // Actually compress the image.
- virtual void compress(const rdr::U32 *buf, const PixelFormat *fmt,
- int w, int h, int stride);
-
- // Access results of the compression.
- virtual size_t getDataLength() { return m_cdata_ready; }
- virtual const char *getDataPtr() { return (const char *)m_cdata; }
-
- public:
- // Our implementation of JPEG destination manager. These three
- // functions should never be called directly. They are made public
- // because they should be accessible from C-compatible functions
- // called by the JPEG library.
- void initDestination();
- bool emptyOutputBuffer();
- void termDestination();
-
- protected:
- static const int ALLOC_CHUNK_SIZE;
- static const int DEFAULT_QUALITY;
-
- struct jpeg_compress_struct m_cinfo;
- struct jpeg_error_mgr m_jerr;
-
- unsigned char *m_cdata;
- size_t m_cdata_allocated;
- size_t m_cdata_ready;
- };
-
-}
-
-#endif // __JPEGCOMPRESSOR_H__
-
+++ /dev/null
-/* Copyright (C) 2007 Constantin Kaplinsky. All Rights Reserved.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#ifdef HAVE_COMMON_CONFIG_H
-#include <common-config.h>
-#endif
-
-#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_CL
-#include <rfb/IrixCLJpegCompressor.h>
-#endif
-#ifdef HAVE_DMEDIA
-#include <rfb/IrixDMJpegCompressor.h>
-#endif
-
-using namespace rfb;
-
-static LogWriter vlog("JpegEncoder");
-
-BoolParameter JpegEncoder::useHardwareJPEG
-("UseHardwareJPEG",
- "Use hardware-accelerated JPEG compressor for video if available",
- true);
-
-const int JpegEncoder::qualityMap[10] = {
- 2, 10, 15, 25, 37, 50, 60, 70, 80, 90
-};
-
-JpegEncoder::JpegEncoder(SMsgWriter* writer_) : writer(writer_), jcomp(0)
-{
-#ifdef HAVE_DMEDIA
-#ifdef DEBUG_FORCE_CL
- vlog.debug("DEBUG: skipping IRIX DM JPEG compressor");
-#else
- if (!jcomp && useHardwareJPEG) {
- vlog.debug("trying IRIX DM JPEG compressor");
- IrixDMJpegCompressor *dmComp = new IrixDMJpegCompressor;
- if (dmComp->isValid()) {
- vlog.debug("initialized IRIX DM JPEG compressor successfully");
- jcomp = dmComp;
- } else {
- vlog.error("warning: could not create IRIX DM JPEG compressor");
- delete dmComp;
- }
- }
-#endif
-#endif
-
-#ifdef HAVE_CL
- if (!jcomp && useHardwareJPEG) {
- vlog.debug("trying IRIX CL JPEG compressor");
- IrixCLJpegCompressor *clComp = new IrixCLJpegCompressor;
- if (clComp->isValid()) {
- vlog.debug("initialized IRIX CL JPEG compressor successfully");
- jcomp = clComp;
- } else {
- vlog.error("warning: could not create IRIX CL JPEG compressor");
- delete clComp;
- }
- }
-#endif
-
- if (!jcomp) {
- if (useHardwareJPEG) {
- vlog.info("no hardware JPEG compressor available");
- }
- vlog.debug("using software JPEG compressor");
- jcomp = new StandardJpegCompressor;
- }
- jcomp->setQuality(qualityMap[6]);
-}
-
-JpegEncoder::~JpegEncoder()
-{
- delete jcomp;
-}
-
-void JpegEncoder::setQualityLevel(int level)
-{
- if (level < 0) {
- level = 0;
- } else if (level > 9) {
- level = 9;
- }
- jcomp->setQuality(qualityMap[level]);
-}
-
-bool JpegEncoder::isPixelFormatSupported(PixelBuffer* pb) const
-{
- 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);
- rdr::OutStream* os = writer->getOutStream();
-
- // Get access to pixel data
- int stride;
- const rdr::U32* pixels = (const rdr::U32 *)pb->getPixelsR(r, &stride);
- const PixelFormat& fmt = pb->getPF();
-
- // Try to encode data
- jcomp->compress(pixels, &fmt, r.width(), r.height(), stride);
-
- // If not successful, switch to StandardJpegCompressor
- if (jcomp->getDataLength() == 0) {
- vlog.info("switching to standard software JPEG compressor");
- delete jcomp;
- jcomp = new StandardJpegCompressor;
- jcomp->setQuality(qualityMap[6]);
- jcomp->compress(pixels, &fmt, r.width(), r.height(), stride);
- }
-
- // Write Tight-encoded header and JPEG data.
- os->writeU8(0x09 << 4);
- os->writeCompactLength(jcomp->getDataLength());
- os->writeBytes(jcomp->getDataPtr(), jcomp->getDataLength());
-
- writer->endRect();
-}
-
+++ /dev/null
-/* Copyright (C) 2007 Constantin Kaplinsky. All Rights Reserved.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-#ifndef __RFB_JPEGENCODER_H__
-#define __RFB_JPEGENCODER_H__
-
-#include <rfb/SMsgWriter.h>
-#include <rfb/PixelBuffer.h>
-#include <rfb/JpegCompressor.h>
-#include <rfb/Configuration.h>
-
-//
-// JPEG Encoder.
-// NOTE: JpegEncoder class is NOT derived from Encoder, because we need
-// access to the original server's framebuffer, without extra pixel
-// copying and with no pixel format translation.
-//
-
-namespace rfb {
-
- class JpegEncoder {
- public:
- JpegEncoder(SMsgWriter* writer);
- virtual ~JpegEncoder();
-
- virtual void setQualityLevel(int level);
- virtual bool isPixelFormatSupported(PixelBuffer* pb) const;
- virtual void writeRect(PixelBuffer* pb, const Rect& r);
-
- static BoolParameter useHardwareJPEG;
-
- private:
- SMsgWriter* writer;
- JpegCompressor* jcomp;
-
- static const int qualityMap[10];
- };
-
-}
-
-#endif
FileWriter.h fttypes.h hextileConstants.h hextileDecode.h \
HextileDecoder.h hextileEncodeBetter.h hextileEncode.h \
HextileEncoder.h Hostname.h HTTPServer.h ImageGetter.h InputHandler.h \
- IrixCLJpegCompressor.h IrixDMIC_RawToJpeg.h IrixDMJpegCompressor.h \
- JpegCompressor.h JpegEncoder.h KeyRemapper.h keysymdef.h \
+ KeyRemapper.h keysymdef.h \
ListConnInfo.h Logger_file.h Logger.h Logger_stdio.h LogWriter.h \
msgTypes.h Password.h PixelBuffer.h PixelFormat.h Pixel.h \
RawDecoder.h RawEncoder.h Rect.h Region.h rreDecode.h RREDecoder.h \
CSecurityVncAuth.cxx CapsContainer.cxx CapsList.cxx \
ComparingUpdateTracker.cxx Configuration.cxx ConnParams.cxx \
Cursor.cxx Decoder.cxx d3des.c Encoder.cxx FileInfo.cxx \
- FileManager.cxx FileReader.cxx FileWriter.cxx JpegCompressor.cxx \
- JpegEncoder.cxx HTTPServer.cxx HextileDecoder.cxx HextileEncoder.cxx \
+ FileManager.cxx FileReader.cxx FileWriter.cxx \
+ HTTPServer.cxx HextileDecoder.cxx HextileEncoder.cxx \
KeyRemapper.cxx LogWriter.cxx Logger.cxx Logger_file.cxx \
Logger_stdio.cxx Password.cxx PixelBuffer.cxx PixelFormat.cxx \
RREEncoder.cxx RREDecoder.cxx RawDecoder.cxx RawEncoder.cxx \
librfb_la_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/../win
librfb_la_LIBADD =
-if IRIX_COMPRESS
-librfb_la_SOURCES += IrixCLJpegCompressor.cxx
-librfb_la_LIBADD += -lcl
-endif
-if IRIX_MEDIA
-librfb_la_SOURCES += IrixDMJpegCompressor.cxx IrixDMIC_RawToJpeg.cxx
-librfb_la_LIBADD += -ldmedia
-endif
-
if INCLUDED_JPEG
librfb_la_CPPFLAGS += -I$(top_srcdir)/jpeg
librfb_la_LIBADD += $(top_srcdir)/jpeg/libjpeg.la
: readyForSetColourMapEntries(false),
is(0), os(0), reader_(0), writer_(0),
security(0), securityFactory(secFact), state_(RFBSTATE_UNINITIALISED),
- reverseConnection(reverseConnection_),
- m_videoSelectionEnabled(false)
+ reverseConnection(reverseConnection_)
{
defaultMajorVersion = 3;
defaultMinorVersion = 8;
os = os_;
}
-void SConnection::setProtocolOptions(bool enableVideoSelection)
-{
- m_videoSelectionEnabled = enableVideoSelection;
-}
-
void SConnection::initialiseProtocol()
{
cp.writeVersion(os);
ccaps.addTightExt(msgTypeFileDeleteRequest, "FTC_RMRQ");
*/
- if (m_videoSelectionEnabled) {
- ccaps.addTightExt(msgTypeVideoRectangleSelection, "VRECTSEL");
- }
-
//
// Advertise all supported encoding types (except raw encoding).
//
// (i.e. SConnection will not delete them).
void setStreams(rdr::InStream* is, rdr::OutStream* os);
- // setProtocolOptions() configures TightVNC-specific protocol options.
- // It can be optionally called before calling initialiseProtocol().
- // See also: VNCServerST::enableVideoSelection();
- void setProtocolOptions(bool enableVideoSelection);
-
// initialiseProtocol() should be called once the streams and security
// types are set. Subsequently, processMsg() should be called whenever
// there is data to read on the InStream.
SSecurityFactory* securityFactory;
stateEnum state_;
bool reverseConnection;
-
- // TightVNC-specific protocol options.
- bool m_videoSelectionEnabled;
};
}
#endif
{
}
-void SMsgHandler::setVideoRectangle(const Rect& r)
-{
-}
virtual void setEncodings(int nEncodings, rdr::U32* encodings);
virtual void framebufferUpdateRequest(const Rect& r, bool incremental);
- virtual void setVideoRectangle(const Rect& r);
-
// InputHandler interface
// The InputHandler methods will be called for the corresponding messages.
handler->clientCutText(ca.buf, len);
}
-void SMsgReader::readVideoRectangleSelection()
-{
- (void)is->readU8();
- int x = is->readU16();
- int y = is->readU16();
- int w = is->readU16();
- int h = is->readU16();
- Rect rect(x, y, x+w, y+h);
-
- if (!rect.is_empty()) {
- vlog.debug("Video area selected by client: %dx%d at (%d,%d)",
- w, h, x, y);
- } else if (x != 0 || y != 0 || w != 0 || h != 0) {
- vlog.debug("Empty video area selected by client: %dx%d at (%d,%d)",
- w, h, x, y);
- rect.clear();
- } else {
- vlog.debug("Video area discarded by client");
- }
- handler->setVideoRectangle(rect);
-}
-
virtual void readPointerEvent();
virtual void readClientCutText();
- // Read TightVNC-specific protocol messages.
- virtual void readVideoRectangleSelection();
-
SMsgReader(SMsgHandler* handler, rdr::InStream* is);
SMsgHandler* handler;
case msgTypeFileRenameRequest:
case msgTypeFileDeleteRequest: handler->processFTMsg(msgType); break;
- case msgTypeVideoRectangleSelection: readVideoRectangleSelection(); break;
-
default:
fprintf(stderr, "unknown message type %d\n", msgType);
throw Exception("unknown message type");
#include <rfb/UpdateTracker.h>
#include <rfb/SMsgWriter.h>
#include <rfb/LogWriter.h>
-#include <rfb/JpegEncoder.h>
using namespace rfb;
bytesSent[i] = 0;
rectsSent[i] = 0;
}
- jpegEncoder = new JpegEncoder(this);
}
SMsgWriter::~SMsgWriter()
vlog.info(" raw bytes equivalent %d, compression ratio %f",
rawBytesEquivalent, (double)rawBytesEquivalent / bytes);
delete [] imageBuf;
- delete jpegEncoder;
}
void SMsgWriter::writeSetColourMapEntries(int firstColour, int nColours,
encoders[encoding]->setCompressLevel(cp->compressLevel);
encoders[encoding]->setQualityLevel(cp->qualityLevel);
- if (cp->qualityLevel != -1)
- jpegEncoder->setQualityLevel(cp->qualityLevel);
}
int SMsgWriter::getNumRects(const Rect &r)
return encoders[encoding]->writeRect(r, ig, actual);
}
-bool SMsgWriter::canUseJpegEncoder(PixelBuffer *pb) const
-{
- return (cp->qualityLevel != -1 && jpegEncoder->isPixelFormatSupported(pb));
-}
-
-void SMsgWriter::writeJpegRect(PixelBuffer *pb, const Rect& r)
-{
- jpegEncoder->writeRect(pb, r);
-}
-
void SMsgWriter::writeCopyRect(const Rect& r, int srcX, int srcY)
{
startRect(r,encodingCopyRect);
class ColourMap;
class Region;
class UpdateInfo;
- class JpegEncoder;
class WriteSetCursorCallback {
public:
virtual void writeCopyRect(const Rect& r, int srcX, int srcY);
- 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;
rdr::OutStream* os;
Encoder* encoders[encodingMax+1];
- JpegEncoder* jpegEncoder;
int lenBeforeRect;
unsigned int currentEncoding;
int updatesSent;
int bytesSent[encodingMax+1];
int rectsSent[encodingMax+1];
int rawBytesEquivalent;
- // FIXME: Gather statistics for JpegEncoder as well.
rdr::U8* imageBuf;
int imageBufSize;
"Prompt the local user to accept or reject incoming connections.",
false);
-// TightVNC-specific parameters
-rfb::IntParameter rfb::Server::videoPriority
-("VideoPriority",
- "Priority of sending video updates (0..8)",
- 2, 0, 8);
static BoolParameter sendCutText;
static BoolParameter queryConnect;
- // TightVNC-specific parameters
- static IntParameter videoPriority;
-
};
};
ut->add_changed(tmp);
}
-void ClippingUpdateTracker::set_video_area(const Rect &rect) {
- ut->set_video_area(rect.intersect(clipRect));
-}
-
// SimpleUpdateTracker
SimpleUpdateTracker::SimpleUpdateTracker(bool use_copyrect) {
return;
}
-void SimpleUpdateTracker::set_video_area(const Rect &rect)
-{
- video_area = rect;
-}
-
-//
-// subtract() is called to mark some region as unchanged. We just remove that
-// region from both `copied' and `changed' regions. Note that `video_area' is
-// not affected intentionally; we assume that video is continuously changing,
-// so it should always be treated as "changed".
-//
-
void SimpleUpdateTracker::subtract(const Region& region) {
copied.assign_subtract(region);
changed.assign_subtract(region);
void SimpleUpdateTracker::getUpdateInfo(UpdateInfo* info, const Region& clip)
{
- changed.assign_subtract(video_area);
- copied.assign_subtract(changed.union_(video_area));
+ copied.assign_subtract(changed);
info->changed = changed.intersect(clip);
info->copied = copied.intersect(clip);
info->copy_delta = copy_delta;
- // FIXME: Using get_bounding_rect() is not what should actually be done!
- // We should use the biggest inner rectangle of the `clip' instead.
- // From the other side, `clip' is usually just a sole rectangle.
- info->video_area = video_area.intersect(clip.get_bounding_rect());
}
void SimpleUpdateTracker::copyTo(UpdateTracker* to) const {
to->add_copied(copied, copy_delta);
if (!changed.is_empty())
to->add_changed(changed);
- to->set_video_area(video_area);
}
Region changed;
Region copied;
Point copy_delta;
- Rect video_area;
bool is_empty() const {
- return copied.is_empty() && changed.is_empty() && video_area.is_empty();
+ return copied.is_empty() && changed.is_empty();
}
// NOTE: We do not ever use UpdateInfo::numRects(), because Tight encoding
// complicates computing the number of rectangles.
/*
int numRects() const {
- return copied.numRects() + changed.numRects() + !video_area.is_empty();
+ return copied.numRects() + changed.numRects();
}
*/
};
virtual void add_changed(const Region ®ion) = 0;
virtual void add_copied(const Region &dest, const Point &delta) = 0;
- virtual void set_video_area(const Rect &rect) = 0;
};
class ClippingUpdateTracker : public UpdateTracker {
virtual void add_changed(const Region ®ion);
virtual void add_copied(const Region &dest, const Point &delta);
- virtual void set_video_area(const Rect &rect);
protected:
UpdateTracker* ut;
Rect clipRect;
virtual void add_changed(const Region ®ion);
virtual void add_copied(const Region &dest, const Point &delta);
- virtual void set_video_area(const Rect &rect);
virtual void subtract(const Region& region);
// Fill the supplied UpdateInfo structure with update information
// FIXME: Provide getUpdateInfo() with no clipping, for better efficiency.
virtual void getUpdateInfo(UpdateInfo* info, const Region& cliprgn);
- // Get coordinates of the video rectangle
- virtual const Rect& getVideoArea() const {
- return video_area;
- }
-
// Copy the contained updates to another tracker
virtual void copyTo(UpdateTracker* to) const;
// Move the entire update region by an offset
- void translate(const Point& p) {
- changed.translate(p);
- copied.translate(p);
- video_area.translate(p);
- }
+ void translate(const Point& p) {changed.translate(p); copied.translate(p);}
- virtual bool is_empty() const {
- return changed.is_empty() && copied.is_empty() && video_area.is_empty();
- }
-
- // NOTE: We do not clear video_area intentionally.
- virtual void clear() {
- changed.clear();
- copied.clear();
- }
+ virtual bool is_empty() const {return changed.is_empty() && copied.is_empty();}
+ virtual void clear() {changed.clear(); copied.clear();};
protected:
Region changed;
Region copied;
Point copy_delta;
bool copy_enabled;
-
- // We can track one rectangle on the screen as a "video area". We assume
- // it is changing continuously, in whole. Thus, we don't need to detect
- // and track individual changes in the video area -- we can assume it's
- // always in the changed state.
- Rect video_area;
};
}
bool VNCSConnectionST::init()
{
try {
- setProtocolOptions(server->isVideoSelectionEnabled());
initialiseProtocol();
} catch (rdr::Exception& e) {
close(e.str());
}
// If there were update requests, try to send a framebuffer update.
- // We don't send updates immediately on requests for two reasons:
- // (1) If a video area is set, we don't want to send it on every
- // update request. We should gobble all the pending update
- // requests and send just one update.
- // (2) This way, we give higher priority to user actions such as
- // keyboard and pointer events.
+ // We don't send updates immediately on requests as this way, we
+ // give higher priority to user actions such as keyboard and
+ // pointer events.
if (!requested.is_empty()) {
writeFramebufferUpdate();
}
}
}
-void VNCSConnectionST::setVideoRectangle(const Rect& r)
-{
- server->setVideoRectangle(r);
-}
-
void VNCSConnectionST::setInitialColourMap()
{
setColourMapEntries(0, 0);
updates.enable_copyrect(cp.useCopyRect);
- static int counter = 1;
- if (--counter > 0) {
- server->checkVideoUpdate();
- } else {
- counter = rfb::Server::videoPriority;
- server->checkUpdate();
- }
-
- // If VideoPriority is 0, convert video updates to normal updates.
-
- if (rfb::Server::videoPriority == 0) {
- Region videoRegion(updates.getVideoArea());
- updates.add_changed(videoRegion);
- Rect nullRect(0, 0, 0, 0);
- updates.set_video_area(nullRect);
- }
+ server->checkUpdate();
// Get the lists of updates. Prior to exporting the data to the `ui' object,
// getUpdateInfo() will normalize the `updates' object such way that its
- // `changed', `copied' and `video_area' regions would not intersect.
+ // `changed' and `copied' regions would not intersect.
UpdateInfo ui;
updates.getUpdateInfo(&ui, requested);
writer()->setupCurrentEncoder();
int nRects = (ui.copied.numRects() +
(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;
}
writer()->writeFramebufferUpdateStart(nRects);
- 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);
void add_copied(const Region& dest, const Point& delta) {
updates.add_copied(dest, delta);
}
- void set_video_area(const Rect &rect) { updates.set_video_area(rect); }
const char* getPeerEndpoint() const {return peerEndpoint.buf;}
virtual void setInitialColourMap();
virtual void supportsLocalCursor();
- virtual void setVideoRectangle(const Rect& r);
-
// setAccessRights() allows a security package to limit the access rights
// of a VNCSConnectioST to the server. These access rights are applied
// such that the actual rights granted are the minimum of the server's
securityFactory(sf ? sf : &defaultSecurityFactory),
queryConnectionHandler(0), keyRemapper(&KeyRemapper::defInstance),
useEconomicTranslate(false),
- lastConnectionTime(0), disableclients(false),
- m_videoSelectionEnabled(false)
+ lastConnectionTime(0), disableclients(false)
{
lastUserInputTime = lastDisconnectTime = time(0);
slog.debug("creating single-threaded server %s", name.buf);
slog.debug("no authenticated clients - stopping desktop");
desktopStarted = false;
desktop->stop();
- setVideoRectangle(Rect(0, 0, 0, 0));
}
return;
}
if (pb) {
comparer = new ComparingUpdateTracker(pb);
- applyVideoRectangle();
cursor.setPF(pb->getPF());
renderedCursor.setPF(pb->getPF());
}
}
-void VNCServerST::set_video_area(const Rect &rect)
-{
- if (comparer != 0) {
- comparer->set_video_area(rect);
- }
-}
-
bool VNCServerST::clientsReadyForUpdate()
{
std::list<VNCSConnectionST*>::iterator ci;
if (ui.is_empty() && !(renderCursor && renderedCursorInvalid))
return;
- Region toCheck = ui.changed.union_(ui.copied).union_(ui.video_area);
+ Region toCheck = ui.changed.union_(ui.copied);
if (renderCursor) {
Rect clippedCursorRect
ci_next = ci; ci_next++;
(*ci)->add_copied(ui.copied, ui.copy_delta);
(*ci)->add_changed(ui.changed);
- (*ci)->set_video_area(ui.video_area);
}
comparer->clear();
}
-void VNCServerST::checkVideoUpdate()
-{
- const Rect &videoRect = comparer->getVideoArea();
- Region videoRegion(videoRect);
-
- if (!videoRegion.is_empty()) {
- pb->grabRegion(videoRegion);
-
- std::list<VNCSConnectionST*>::iterator ci, ci_next;
- for (ci = clients.begin(); ci != clients.end(); ci = ci_next) {
- ci_next = ci; ci_next++;
- (*ci)->set_video_area(videoRect);
- }
- }
-}
-
void VNCServerST::getConnInfo(ListConnInfo * listConn)
{
listConn->Clear();
}
}
-void VNCServerST::enableVideoSelection(bool enable)
-{
- slog.debug("Enabling video selection");
- m_videoSelectionEnabled = enable;
- applyVideoRectangle();
-}
-
-bool VNCServerST::isVideoSelectionEnabled() const
-{
- return m_videoSelectionEnabled;
-}
-
-void VNCServerST::setVideoRectangle(const Rect& r)
-{
- m_videoRect = r;
- applyVideoRectangle();
-}
-
-void VNCServerST::setDefaultVideoRectangle(const Rect& r)
-{
- m_defaultVideoRect = r;
- applyVideoRectangle();
-}
-
-void VNCServerST::applyVideoRectangle()
-{
- if (pb != 0) {
- if (isVideoSelectionEnabled() && !m_videoRect.is_empty()) {
- slog.debug("Applying video selection");
- set_video_area(m_videoRect);
- } else {
- if (!m_defaultVideoRect.is_empty()) {
- slog.debug("Applying default video area");
- } else {
- slog.debug("Applying empty video area");
- }
- set_video_area(m_defaultVideoRect);
- }
- }
-}
virtual void serverCutText(const char* str, int len);
virtual void add_changed(const Region ®ion);
virtual void add_copied(const Region &dest, const Point &delta);
- virtual void set_video_area(const Rect &rect);
virtual bool clientsReadyForUpdate();
virtual void tryUpdate();
virtual void setCursor(int width, int height, const Point& hotspot,
void setFTManager(rfb::SFileTransferManager *pFTManager) { m_pFTManager = pFTManager; };
- // Enable/disable support for TightVNC-specific VideoRectangleSelection
- // client message. This is a protocol option that lets a client select a
- // rectangle to be treated by the server as video data. Once selected, this
- // part of the framebuffer will be sent using JpegEncoder, on each update
- // request, as we expect that video data is changing continuously. By
- // default, this option is disabled, as it's rather a specialized feature
- // and video selection GUI can confuse users of the TigerVNC client.
- void enableVideoSelection(bool enable);
- bool isVideoSelectionEnabled() const;
-
- void setVideoRectangle(const Rect& r);
- void setDefaultVideoRectangle(const Rect& r);
-
protected:
friend class VNCSConnectionST;
bool needRenderedCursor();
void checkUpdate();
- void checkVideoUpdate();
SSecurityFactory* securityFactory;
QueryConnectionHandler* queryConnectionHandler;
time_t lastConnectionTime;
bool disableclients;
-
- bool m_videoSelectionEnabled;
- Rect m_videoRect;
- Rect m_defaultVideoRect;
-
- void applyVideoRectangle();
};
};
const int msgTypeFileDeleteRequest = 139;
const int msgTypeEnableContinuousUpdates = 150;
- const int msgTypeVideoRectangleSelection = 151;
}
#endif
# End Source File\r
# Begin Source File\r
\r
-SOURCE=.\JpegCompressor.cxx\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\JpegEncoder.cxx\r
-# End Source File\r
-# Begin Source File\r
-\r
SOURCE=.\KeyRemapper.cxx\r
# End Source File\r
# Begin Source File\r
# End Source File\r
# Begin Source File\r
\r
-SOURCE=.\JpegCompressor.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\JpegEncoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
SOURCE=.\KeyRemapper.h\r
# End Source File\r
# Begin Source File\r
server = (VNCServerST *)vs;
server->setPixelBuffer(pb);
- server->setDefaultVideoRectangle(geometry->getVideoRect());
running = true;
}
VNCServerST server("x0vncserver", &desktop);
QueryConnHandler qcHandler(dpy, &server);
server.setQueryConnectionHandler(&qcHandler);
- server.enableVideoSelection(true);
TcpListener listener((int)rfbport);
vlog.info("Listening on port %d", (int)rfbport);