diff options
Diffstat (limited to 'common/rfb/EncodeManager.cxx')
-rw-r--r-- | common/rfb/EncodeManager.cxx | 159 |
1 files changed, 93 insertions, 66 deletions
diff --git a/common/rfb/EncodeManager.cxx b/common/rfb/EncodeManager.cxx index 67a32f5b..6a63fa6f 100644 --- a/common/rfb/EncodeManager.cxx +++ b/common/rfb/EncodeManager.cxx @@ -25,14 +25,17 @@ #include <stdlib.h> +#include <core/LogWriter.h> +#include <core/string.h> + +#include <rfb/Cursor.h> #include <rfb/EncodeManager.h> #include <rfb/Encoder.h> #include <rfb/Palette.h> #include <rfb/SConnection.h> #include <rfb/SMsgWriter.h> #include <rfb/UpdateTracker.h> -#include <rfb/LogWriter.h> -#include <rfb/util.h> +#include <rfb/encodings.h> #include <rfb/RawEncoder.h> #include <rfb/RREEncoder.h> @@ -43,7 +46,7 @@ using namespace rfb; -static LogWriter vlog("EncodeManager"); +static core::LogWriter vlog("EncodeManager"); // Split each rectangle into smaller ones no larger than this area, // and no wider than this width. @@ -191,11 +194,11 @@ void EncodeManager::logStats() ratio = (double)copyStats.equivalent / copyStats.bytes; vlog.info(" %s: %s, %s", "Copies", - siPrefix(copyStats.rects, "rects").c_str(), - siPrefix(copyStats.pixels, "pixels").c_str()); + core::siPrefix(copyStats.rects, "rects").c_str(), + core::siPrefix(copyStats.pixels, "pixels").c_str()); vlog.info(" %*s %s (1:%g ratio)", (int)strlen("Copies"), "", - iecPrefix(copyStats.bytes, "B").c_str(), ratio); + core::iecPrefix(copyStats.bytes, "B").c_str(), ratio); } for (i = 0;i < stats.size();i++) { @@ -221,21 +224,21 @@ void EncodeManager::logStats() ratio = (double)stats[i][j].equivalent / stats[i][j].bytes; vlog.info(" %s: %s, %s", encoderTypeName((EncoderType)j), - siPrefix(stats[i][j].rects, "rects").c_str(), - siPrefix(stats[i][j].pixels, "pixels").c_str()); + core::siPrefix(stats[i][j].rects, "rects").c_str(), + core::siPrefix(stats[i][j].pixels, "pixels").c_str()); vlog.info(" %*s %s (1:%g ratio)", (int)strlen(encoderTypeName((EncoderType)j)), "", - iecPrefix(stats[i][j].bytes, "B").c_str(), ratio); + core::iecPrefix(stats[i][j].bytes, "B").c_str(), ratio); } } ratio = (double)equivalent / bytes; vlog.info(" Total: %s, %s", - siPrefix(rects, "rects").c_str(), - siPrefix(pixels, "pixels").c_str()); + core::siPrefix(rects, "rects").c_str(), + core::siPrefix(pixels, "pixels").c_str()); vlog.info(" %s (1:%g ratio)", - iecPrefix(bytes, "B").c_str(), ratio); + core::iecPrefix(bytes, "B").c_str(), ratio); } bool EncodeManager::supported(int encoding) @@ -252,12 +255,12 @@ bool EncodeManager::supported(int encoding) } } -bool EncodeManager::needsLosslessRefresh(const Region& req) +bool EncodeManager::needsLosslessRefresh(const core::Region& req) { return !lossyRegion.intersect(req).is_empty(); } -int EncodeManager::getNextLosslessRefresh(const Region& req) +int EncodeManager::getNextLosslessRefresh(const core::Region& req) { // Do we have something we can send right away? if (!pendingRefreshRegion.intersect(req).is_empty()) @@ -269,12 +272,19 @@ int EncodeManager::getNextLosslessRefresh(const Region& req) return recentChangeTimer.getNextTimeout(); } -void EncodeManager::pruneLosslessRefresh(const Region& limits) +void EncodeManager::pruneLosslessRefresh(const core::Region& limits) { lossyRegion.assign_intersect(limits); pendingRefreshRegion.assign_intersect(limits); } +void EncodeManager::forceRefresh(const core::Region& req) +{ + lossyRegion.assign_union(req); + if (!recentChangeTimer.isStarted()) + pendingRefreshRegion.assign_union(req); +} + void EncodeManager::writeUpdate(const UpdateInfo& ui, const PixelBuffer* pb, const RenderedCursor* renderedCursor) { @@ -286,15 +296,16 @@ void EncodeManager::writeUpdate(const UpdateInfo& ui, const PixelBuffer* pb, recentChangeTimer.start(RecentChangeTimeout); } -void EncodeManager::writeLosslessRefresh(const Region& req, const PixelBuffer* pb, +void EncodeManager::writeLosslessRefresh(const core::Region& req, + const PixelBuffer* pb, const RenderedCursor* renderedCursor, size_t maxUpdateSize) { doUpdate(false, getLosslessRefresh(req, maxUpdateSize), - Region(), Point(), pb, renderedCursor); + {}, {}, pb, renderedCursor); } -void EncodeManager::handleTimeout(Timer* t) +void EncodeManager::handleTimeout(core::Timer* t) { if (t == &recentChangeTimer) { // Any lossy region that wasn't recently updated can @@ -308,13 +319,15 @@ void EncodeManager::handleTimeout(Timer* t) } } -void EncodeManager::doUpdate(bool allowLossy, const Region& changed_, - const Region& copied, const Point& copyDelta, +void EncodeManager::doUpdate(bool allowLossy, const + core::Region& changed_, + const core::Region& copied, + const core::Point& copyDelta, const PixelBuffer* pb, const RenderedCursor* renderedCursor) { int nRects; - Region changed, cursorRegion; + core::Region changed, cursorRegion; updates++; @@ -475,19 +488,20 @@ void EncodeManager::prepareEncoders(bool allowLossy) encoder->setFineQualityLevel(conn->client.fineQualityLevel, conn->client.subsampling); } else { - int level = __rfbmax(conn->client.qualityLevel, - encoder->losslessQuality); - encoder->setQualityLevel(level); + if (conn->client.qualityLevel < encoder->losslessQuality) + encoder->setQualityLevel(encoder->losslessQuality); + else + encoder->setQualityLevel(conn->client.qualityLevel); encoder->setFineQualityLevel(-1, subsampleUndefined); } } } -Region EncodeManager::getLosslessRefresh(const Region& req, - size_t maxUpdateSize) +core::Region EncodeManager::getLosslessRefresh(const core::Region& req, + size_t maxUpdateSize) { - std::vector<Rect> rects; - Region refresh; + std::vector<core::Rect> rects; + core::Region refresh; size_t area; // We make a conservative guess at the compression ratio at 2:1 @@ -500,7 +514,7 @@ Region EncodeManager::getLosslessRefresh(const Region& req, pendingRefreshRegion.intersect(req).get_rects(&rects); while (!rects.empty()) { size_t idx; - Rect rect; + core::Rect rect; // Grab a random rect so we don't keep damaging and restoring the // same rect over and over @@ -514,17 +528,21 @@ Region EncodeManager::getLosslessRefresh(const Region& req, // Use the narrowest axis to avoid getting to thin rects if (rect.width() > rect.height()) { int width = (maxUpdateSize - area) / rect.height(); - rect.br.x = rect.tl.x + __rfbmax(1, width); + if (width < 1) + width = 1; + rect.br.x = rect.tl.x + width; } else { int height = (maxUpdateSize - area) / rect.width(); - rect.br.y = rect.tl.y + __rfbmax(1, height); + if (height < 1) + height = 1; + rect.br.y = rect.tl.y + height; } - refresh.assign_union(Region(rect)); + refresh.assign_union(rect); break; } area += rect.area(); - refresh.assign_union(Region(rect)); + refresh.assign_union(rect); rects.erase(rects.begin() + idx); } @@ -532,11 +550,11 @@ Region EncodeManager::getLosslessRefresh(const Region& req, return refresh; } -int EncodeManager::computeNumRects(const Region& changed) +int EncodeManager::computeNumRects(const core::Region& changed) { int numRects; - std::vector<Rect> rects; - std::vector<Rect>::const_iterator rect; + std::vector<core::Rect> rects; + std::vector<core::Rect>::const_iterator rect; numRects = 0; changed.get_rects(&rects); @@ -566,7 +584,7 @@ int EncodeManager::computeNumRects(const Region& changed) return numRects; } -Encoder *EncodeManager::startRect(const Rect& rect, int type) +Encoder* EncodeManager::startRect(const core::Rect& rect, int type) { Encoder *encoder; int klass, equiv; @@ -587,13 +605,13 @@ Encoder *EncodeManager::startRect(const Rect& rect, int type) if ((encoder->flags & EncoderLossy) && ((encoder->losslessQuality == -1) || (encoder->getQualityLevel() < encoder->losslessQuality))) - lossyRegion.assign_union(Region(rect)); + lossyRegion.assign_union(rect); else - lossyRegion.assign_subtract(Region(rect)); + lossyRegion.assign_subtract(rect); // This was either a rect getting refreshed, or a rect that just got // new content. Either way we should not try to refresh it anymore. - pendingRefreshRegion.assign_subtract(Region(rect)); + pendingRefreshRegion.assign_subtract(rect); return encoder; } @@ -611,12 +629,13 @@ void EncodeManager::endRect() stats[klass][activeType].bytes += length; } -void EncodeManager::writeCopyRects(const Region& copied, const Point& delta) +void EncodeManager::writeCopyRects(const core::Region& copied, + const core::Point& delta) { - std::vector<Rect> rects; - std::vector<Rect>::const_iterator rect; + std::vector<core::Rect> rects; + std::vector<core::Rect>::const_iterator rect; - Region lossyCopy; + core::Region lossyCopy; beforeLength = conn->getOutStream()->length(); @@ -645,20 +664,22 @@ void EncodeManager::writeCopyRects(const Region& copied, const Point& delta) pendingRefreshRegion.assign_subtract(copied); } -void EncodeManager::writeSolidRects(Region *changed, const PixelBuffer* pb) +void EncodeManager::writeSolidRects(core::Region* changed, + const PixelBuffer* pb) { - std::vector<Rect> rects; - std::vector<Rect>::const_iterator rect; + std::vector<core::Rect> rects; + std::vector<core::Rect>::const_iterator rect; changed->get_rects(&rects); for (rect = rects.begin(); rect != rects.end(); ++rect) findSolidRect(*rect, changed, pb); } -void EncodeManager::findSolidRect(const Rect& rect, Region *changed, +void EncodeManager::findSolidRect(const core::Rect& rect, + core::Region* changed, const PixelBuffer* pb) { - Rect sr; + core::Rect sr; int dx, dy, dw, dh; // We start by finding a solid 16x16 block @@ -677,11 +698,11 @@ void EncodeManager::findSolidRect(const Rect& rect, Region *changed, if (dx + dw > rect.br.x) dw = rect.br.x - dx; - pb->getImage(colourValue, Rect(dx, dy, dx+1, dy+1)); + pb->getImage(colourValue, {dx, dy, dx+1, dy+1}); sr.setXYWH(dx, dy, dw, dh); if (checkSolidTile(sr, colourValue, pb)) { - Rect erb, erp; + core::Rect erb, erp; Encoder *encoder; @@ -721,7 +742,7 @@ void EncodeManager::findSolidRect(const Rect& rect, Region *changed, } endRect(); - changed->assign_subtract(Region(erp)); + changed->assign_subtract(erp); // Search remaining areas by recursion // FIXME: Is this the best way to divide things up? @@ -752,15 +773,16 @@ void EncodeManager::findSolidRect(const Rect& rect, Region *changed, } } -void EncodeManager::writeRects(const Region& changed, const PixelBuffer* pb) +void EncodeManager::writeRects(const core::Region& changed, + const PixelBuffer* pb) { - std::vector<Rect> rects; - std::vector<Rect>::const_iterator rect; + std::vector<core::Rect> rects; + std::vector<core::Rect>::const_iterator rect; changed.get_rects(&rects); for (rect = rects.begin(); rect != rects.end(); ++rect) { int w, h, sw, sh; - Rect sr; + core::Rect sr; w = rect->width(); h = rect->height(); @@ -794,7 +816,8 @@ void EncodeManager::writeRects(const Region& changed, const PixelBuffer* pb) } } -void EncodeManager::writeSubRect(const Rect& rect, const PixelBuffer *pb) +void EncodeManager::writeSubRect(const core::Rect& rect, + const PixelBuffer* pb) { PixelBuffer *ppb; @@ -878,7 +901,8 @@ void EncodeManager::writeSubRect(const Rect& rect, const PixelBuffer *pb) endRect(); } -bool EncodeManager::checkSolidTile(const Rect& r, const uint8_t* colourValue, +bool EncodeManager::checkSolidTile(const core::Rect& r, + const uint8_t* colourValue, const PixelBuffer *pb) { const uint8_t* buffer; @@ -902,13 +926,14 @@ bool EncodeManager::checkSolidTile(const Rect& r, const uint8_t* colourValue, } } -void EncodeManager::extendSolidAreaByBlock(const Rect& r, +void EncodeManager::extendSolidAreaByBlock(const core::Rect& r, const uint8_t* colourValue, - const PixelBuffer *pb, Rect* er) + const PixelBuffer* pb, + core::Rect* er) { int dx, dy, dw, dh; int w_prev; - Rect sr; + core::Rect sr; int w_best = 0, h_best = 0; w_prev = r.width(); @@ -958,12 +983,14 @@ void EncodeManager::extendSolidAreaByBlock(const Rect& r, er->br.y = er->tl.y + h_best; } -void EncodeManager::extendSolidAreaByPixel(const Rect& r, const Rect& sr, +void EncodeManager::extendSolidAreaByPixel(const core::Rect& r, + const core::Rect& sr, const uint8_t* colourValue, - const PixelBuffer *pb, Rect* er) + const PixelBuffer* pb, + core::Rect* er) { int cx, cy; - Rect tr; + core::Rect tr; // Try to extend the area upwards. for (cy = sr.tl.y - 1; cy >= r.tl.y; cy--) { @@ -998,7 +1025,7 @@ void EncodeManager::extendSolidAreaByPixel(const Rect& r, const Rect& sr, er->br.x = cx; } -PixelBuffer* EncodeManager::preparePixelBuffer(const Rect& rect, +PixelBuffer* EncodeManager::preparePixelBuffer(const core::Rect& rect, const PixelBuffer *pb, bool convert) { @@ -1063,7 +1090,7 @@ void EncodeManager::OffsetPixelBuffer::update(const PixelFormat& pf, setBuffer(width, height, (uint8_t*)data_, stride_); } -uint8_t* EncodeManager::OffsetPixelBuffer::getBufferRW(const Rect& /*r*/, int* /*stride*/) +uint8_t* EncodeManager::OffsetPixelBuffer::getBufferRW(const core::Rect& /*r*/, int* /*stride*/) { throw std::logic_error("Invalid write attempt to OffsetPixelBuffer"); } |