From 82f7b015eaca970f18d1666c972c95bf674e175e Mon Sep 17 00:00:00 2001 From: Constantin Kaplinsky Date: Fri, 30 May 2008 10:03:30 +0000 Subject: [PATCH] Removed the code for automatic video detection. It interfered with video selection feature of the Java viewer, and did not look good with respect to the impending polling improvements. git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@2566 3789f03b-4d11-0410-bbf8-ca57d06f2519 --- unix/x0vncserver/PollingManager.cxx | 262 +--------------------------- unix/x0vncserver/PollingManager.h | 18 +- unix/x0vncserver/x0vncserver.man | 27 +-- 3 files changed, 7 insertions(+), 300 deletions(-) diff --git a/unix/x0vncserver/PollingManager.cxx b/unix/x0vncserver/PollingManager.cxx index 32f61470..bcc9547c 100644 --- a/unix/x0vncserver/PollingManager.cxx +++ b/unix/x0vncserver/PollingManager.cxx @@ -1,4 +1,4 @@ -/* Copyright (C) 2004-2007 Constantin Kaplinsky. All Rights Reserved. +/* Copyright (C) 2004-2008 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 @@ -15,6 +15,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ + // // PollingManager.cxx // @@ -39,11 +40,6 @@ const int PollingManager::m_pollingOrder[32] = { 19, 3, 27, 11, 29, 13, 5, 21 }; -// FIXME: Check that the parameter's value is in the allowed range. -// This applies to all other parameters as well. -IntParameter PollingManager::m_videoPriority("VideoPriority", - "Priority of sending updates for video area (0..8)", 2); - // // Constructor. // @@ -68,7 +64,6 @@ PollingManager::PollingManager(Display *dpy, Image *image, m_heightTiles((image->xim->height + 31) / 32), m_numTiles(((image->xim->width + 31) / 32) * ((image->xim->height + 31) / 32)), - m_numVideoPasses(0), m_pollingStep(0) { // Get initial screen image. @@ -89,17 +84,11 @@ PollingManager::PollingManager(Display *dpy, Image *image, } m_changeFlags = new bool[m_numTiles]; - m_rateMatrix = new char[m_numTiles]; - m_videoFlags = new char[m_numTiles]; memset(m_changeFlags, 0, m_numTiles * sizeof(bool)); - memset(m_rateMatrix, 0, m_numTiles); - memset(m_videoFlags, 0, m_numTiles); } PollingManager::~PollingManager() { - delete[] m_videoFlags; - delete[] m_rateMatrix; delete[] m_changeFlags; delete m_rowImage; @@ -169,26 +158,6 @@ bool PollingManager::pollScreen() if (!m_server) return false; - // If video data should have higher priority, and video area was - // detected, perform special passes to send video data only. Such - // "video passes" will be performed between normal polling passes. - // No actual polling is performed in a video pass since we know that - // video is changing continuously. - // - // FIXME: Should we move this block into a separate function? - // FIXME: Giving higher priority to video area lengthens video - // detection cycles. Should we do something with that? - if ((int)m_videoPriority > 1 && !m_videoRect.is_empty()) { - if (m_numVideoPasses > 0) { - m_numVideoPasses--; - getScreenRect(m_videoRect); - return true; // we've got changes - } else { - // Normal pass now, but schedule video passes for next calls. - m_numVideoPasses = (int)m_videoPriority - 1; - } - } - // Clear the m_changeFlags[] array, indicating that no changes have // been detected yet. memset(m_changeFlags, 0, m_numTiles * sizeof(bool)); @@ -203,31 +172,14 @@ bool PollingManager::pollScreen() nTilesChanged += checkRow(0, y, m_width); } - // Do the work related to video area detection, if enabled. - bool haveVideoRect = false; - if ((int)m_videoPriority != 0) { - handleVideo(); - if (!m_videoRect.is_empty()) { - getScreenRect(m_videoRect); - haveVideoRect = true; - } - } - DBG_REPORT_CHANGES("After 1st pass"); // If some changes have been detected: if (nTilesChanged) { - // Try to find more changes around. Before doing that, mark the - // video area as changed, to skip comparisons of its pixels. - flagVideoArea(true); - DBG_REPORT_CHANGES("Before checking neighbors"); + // Try to find more changes around. checkNeighbors(); DBG_REPORT_CHANGES("After checking neighbors"); - - // Inform the server about the changes. This time, we mark the - // video area as NOT changed, to prevent reading its pixels again. - flagVideoArea(false); - DBG_REPORT_CHANGES("Before sending"); + // Inform the server about the changes. nTilesChanged = sendChanges(); } @@ -244,7 +196,7 @@ bool PollingManager::pollScreen() } #endif - return (nTilesChanged != 0 || haveVideoRect); + return (nTilesChanged != 0); } int PollingManager::checkRow(int x, int y, int w) @@ -350,33 +302,6 @@ int PollingManager::sendChanges() return nTilesChanged; } -void PollingManager::handleVideo() -{ - // Update counters in m_rateMatrix. - for (int i = 0; i < m_numTiles; i++) - m_rateMatrix[i] += (m_changeFlags[i] != false); - - // Once per eight calls: detect video rectangle by examining - // m_rateMatrix[], then reset counters in m_rateMatrix[]. - if (m_pollingStep % 8 == 0) { - detectVideo(); - memset(m_rateMatrix, 0, m_numTiles); - } -} - -void PollingManager::flagVideoArea(bool value) -{ - if (m_videoRect.is_empty()) - return; - - Rect r(m_videoRect.tl.x / 32, m_videoRect.tl.y / 32, - m_videoRect.br.x / 32, m_videoRect.br.y / 32); - - for (int y = r.tl.y; y < r.br.y; y++) - for (int x = r.tl.x; x < r.br.x; x++) - m_changeFlags[y * m_widthTiles + x] = value; -} - void PollingManager::checkNeighbors() { @@ -461,180 +386,3 @@ PollingManager::printChanges(const char *header) const fprintf(stderr, "\n"); } -void -PollingManager::detectVideo() -{ - // Configurable parameters. - const int VIDEO_THRESHOLD_0 = 3; - const int VIDEO_THRESHOLD_1 = 5; - - // In m_rateMatrix, clear counters corresponding to non-32x32 tiles. - // This will guarantee that the size of the video area is always a - // multiple of 32 pixels. This is important for hardware JPEG encoders. - if (m_width % 32 != 0) { - for (int n = m_widthTiles - 1; n < m_numTiles; n += m_widthTiles) - m_rateMatrix[n] = 0; - } - if (m_height % 32 != 0) { - for (int n = m_numTiles - m_widthTiles; n < m_numTiles; n++) - m_rateMatrix[n] = 0; - } - - // First, detect candidate region that looks like video. In other - // words, find a region that consists of continuously changing - // pixels. Save the result in m_videoFlags[]. - for (int i = 0; i < m_numTiles; i++) { - if (m_rateMatrix[i] <= VIDEO_THRESHOLD_0) { - m_videoFlags[i] = 0; - } else if (m_rateMatrix[i] >= VIDEO_THRESHOLD_1) { - m_videoFlags[i] = 1; - } - } - - // Now, choose the biggest rectangle from that candidate region. - Rect newRect; - getVideoAreaRect(&newRect); - - // Does new rectangle differ from the previously detected one? - // If it does, save new rectangle and inform the server. - if (!newRect.equals(m_videoRect)) { - if (newRect.is_empty()) { - vlog.debug("No video detected"); - } else { - vlog.debug("Detected video %dx%d at (%d,%d)", - newRect.width(), newRect.height(), - newRect.tl.x, newRect.tl.y); - } - m_videoRect = newRect; - m_server->set_video_area(newRect); - } -} - -void -PollingManager::getVideoAreaRect(Rect *result) -{ - int *mx_hlen, *mx_vlen; - constructLengthMatrices(&mx_hlen, &mx_vlen); - - int full_h = m_heightTiles; - int full_w = m_widthTiles; - int x, y; - Rect max_rect(0, 0, 0, 0); - Rect local_rect; - - for (y = 0; y < full_h; y++) { - for (x = 0; x < full_w; x++) { - int max_w = mx_hlen[y * full_w + x]; - int max_h = mx_vlen[y * full_w + x]; - if (max_w > 2 && max_h > 1 && max_h * max_w > (int)max_rect.area()) { - local_rect.tl.x = x; - local_rect.tl.y = y; - findMaxLocalRect(&local_rect, mx_hlen, mx_vlen); - if (local_rect.area() > max_rect.area()) { - max_rect = local_rect; - } - } - } - } - - destroyLengthMatrices(mx_hlen, mx_vlen); - - max_rect.tl.x *= 32; - max_rect.tl.y *= 32; - max_rect.br.x *= 32; - max_rect.br.y *= 32; - if (max_rect.br.x > m_width) - max_rect.br.x = m_width; - if (max_rect.br.y > m_height) - max_rect.br.y = m_height; - *result = max_rect; -} - -void -PollingManager::constructLengthMatrices(int **pmx_h, int **pmx_v) -{ - // Handy shortcuts. - int h = m_heightTiles; - int w = m_widthTiles; - - // Allocate memory. - int *mx_h = new int[h * w]; - memset(mx_h, 0, h * w * sizeof(int)); - int *mx_v = new int[h * w]; - memset(mx_v, 0, h * w * sizeof(int)); - - int x, y, len, i; - - // Fill in horizontal length matrix. - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - len = 0; - while (x + len < w && m_videoFlags[y * w + x + len]) { - len++; - } - for (i = 0; i < len; i++) { - mx_h[y * w + x + i] = len - i; - } - x += len; - } - } - - // Fill in vertical length matrix. - for (x = 0; x < w; x++) { - for (y = 0; y < h; y++) { - len = 0; - while (y + len < h && m_videoFlags[(y + len) * w + x]) { - len++; - } - for (i = 0; i < len; i++) { - mx_v[(y + i) * w + x] = len - i; - } - y += len; - } - } - - *pmx_h = mx_h; - *pmx_v = mx_v; -} - -void -PollingManager::destroyLengthMatrices(int *mx_h, int *mx_v) -{ - delete[] mx_h; - delete[] mx_v; -} - -// NOTE: This function assumes that current tile has non-zero in mx_h[], -// otherwise we get division by zero. -void -PollingManager::findMaxLocalRect(Rect *r, int mx_h[], int mx_v[]) -{ - int idx = r->tl.y * m_widthTiles + r->tl.x; - - // NOTE: Rectangle's maximum width and height are 25 and 18 - // (in tiles, where each tile is usually 32x32 pixels). - int max_w = mx_h[idx]; - if (max_w > 25) - max_w = 25; - int cur_h = 18; - - int best_w = max_w; - int best_area = 1 * best_w; - - for (int i = 0; i < max_w; i++) { - int h = mx_v[idx + i]; - if (h < cur_h) { - cur_h = h; - if (cur_h * max_w <= best_area) - break; - } - if (cur_h * (i + 1) > best_area) { - best_w = i + 1; - best_area = cur_h * best_w; - } - } - - r->br.x = r->tl.x + best_w; - r->br.y = r->tl.y + best_area / best_w; -} - diff --git a/unix/x0vncserver/PollingManager.h b/unix/x0vncserver/PollingManager.h index 09cd5c3a..cedac1a3 100644 --- a/unix/x0vncserver/PollingManager.h +++ b/unix/x0vncserver/PollingManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2004-2007 Constantin Kaplinsky. All Rights Reserved. +/* Copyright (C) 2004-2008 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 @@ -108,8 +108,6 @@ private: int checkRow(int x, int y, int w); int checkColumn(int x, int y, int h, bool *pChangeFlags); int sendChanges(); - void handleVideo(); - void flagVideoArea(bool value); // Check neighboring tiles and update m_changeFlags[]. void checkNeighbors(); @@ -117,13 +115,6 @@ private: // DEBUG: Print the list of changed tiles. void printChanges(const char *header) const; - // Video detection functions. - void detectVideo(); - void getVideoAreaRect(Rect *result); - void constructLengthMatrices(int **pmx_h, int **pmx_v); - void destroyLengthMatrices(int *mx_h, int *mx_v); - void findMaxLocalRect(Rect *r, int *mx_h, int *mx_v); - // Additional images used in polling algorithms. Image *m_rowImage; // one row of the framebuffer Image *m_columnImage; // one column of the framebuffer @@ -137,16 +128,9 @@ private: // in that tile. bool *m_changeFlags; - char *m_rateMatrix; - char *m_videoFlags; - Rect m_videoRect; - int m_numVideoPasses; - unsigned int m_pollingStep; static const int m_pollingOrder[]; - static IntParameter m_videoPriority; - #ifdef DEBUG private: diff --git a/unix/x0vncserver/x0vncserver.man b/unix/x0vncserver/x0vncserver.man index 7dbda98a..850f1d7b 100644 --- a/unix/x0vncserver/x0vncserver.man +++ b/unix/x0vncserver/x0vncserver.man @@ -1,4 +1,4 @@ -.TH X0VNCSERVER 1 "January 7, 2008" "TightVNC" "TightVNC Manual" +.TH X0VNCSERVER 1 "May 30, 2008" "TightVNC" "TightVNC Manual" .SH NAME x0vncserver \- TightVNC Server for real X displays .SH SYNOPSIS @@ -137,31 +137,6 @@ screen. Default is 35. Milliseconds per one polling cycle. Actual interval may be dynamically adjusted to satisfy \fBMaxProcessorUsage\fP setting. Default is 30. .TP -.B VideoPriority -Specify the priority of sending video area updates. \fBx0vncserver\fP can -detect video areas on the screen and handle them separately for improved -performance. This parameter controls how often video area will be sent to -clients as compared to the rest of the screen. The priority must be an -integer between 0 and 8, and the default value is 2. - -\fBVideoPriority\fP set to 0 disables video detection completely, so -\fBx0vncserver\fP will not use any video-specific tricks. - -The value 1 gives the same priority both to video and to other pixels. That -differs from the value 0 \- overall performance can be much better if there -is some video on the screen. That's because video-specific polling and -encoding algorithms can be used. - -Higher values give more priority to video. For example, \fBVideoPriority\fP -set to 5 specifies that the rate of sending video will be five times higher -than the rate of updating the rest of the screen. - -\fBNote:\fP with high \fBVideoPriority\fP values, video detection will work -slower. For example, when the video area was moved, this fact will be -discovered with a longer delay. That's because high priority values make the -server send video with highest rate possible, without spending time on -polling and video detection. -.TP .B CompareFB Perform pixel comparison on framebuffer to reduce unnecessary updates. Default is on. -- 2.39.5