mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 05:57:29 +02:00
added suppression of duplicate voxel packets to save on bit/packet rate
This commit is contained in:
parent
d486fc8c0e
commit
14cf5b04b5
3 changed files with 67 additions and 2 deletions
|
@ -27,6 +27,9 @@ VoxelNodeData::VoxelNodeData(Node* owningNode) :
|
||||||
{
|
{
|
||||||
_voxelPacket = new unsigned char[MAX_VOXEL_PACKET_SIZE];
|
_voxelPacket = new unsigned char[MAX_VOXEL_PACKET_SIZE];
|
||||||
_voxelPacketAt = _voxelPacket;
|
_voxelPacketAt = _voxelPacket;
|
||||||
|
_lastVoxelPacket = new unsigned char[MAX_VOXEL_PACKET_SIZE];
|
||||||
|
_lastVoxelPacketLength = 0;
|
||||||
|
_duplicatePacketCount = 0;
|
||||||
resetVoxelPacket();
|
resetVoxelPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,9 +40,55 @@ void VoxelNodeData::initializeVoxelSendThread(VoxelServer* voxelServer) {
|
||||||
_voxelSendThread->initialize(true);
|
_voxelSendThread->initialize(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VoxelNodeData::packetIsDuplicate() const {
|
||||||
|
if (_lastVoxelPacketLength == getPacketLength()) {
|
||||||
|
return memcmp(_lastVoxelPacket, _voxelPacket, getPacketLength()) == 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VoxelNodeData::shouldSuppressDuplicatePacket() {
|
||||||
|
bool shouldSuppress = false; // assume we won't suppress
|
||||||
|
|
||||||
|
// only consider duplicate packets
|
||||||
|
if (packetIsDuplicate()) {
|
||||||
|
_duplicatePacketCount++;
|
||||||
|
|
||||||
|
// If this is the first suppressed packet, remember our time...
|
||||||
|
if (_duplicatePacketCount == 1) {
|
||||||
|
_firstSuppressedPacket = usecTimestampNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
// How long has it been since we've sent one, if we're still under our max time, then keep considering
|
||||||
|
// this packet for suppression
|
||||||
|
uint64_t now = usecTimestampNow();
|
||||||
|
long sinceFirstSuppressedPacket = now - _firstSuppressedPacket;
|
||||||
|
const long MAX_TIME_BETWEEN_DUPLICATE_PACKETS = 1000 * 1000; // 1 second.
|
||||||
|
|
||||||
|
if (sinceFirstSuppressedPacket < MAX_TIME_BETWEEN_DUPLICATE_PACKETS) {
|
||||||
|
// Finally, if we know we've sent at least one duplicate out, then suppress the rest...
|
||||||
|
if (_duplicatePacketCount > 1) {
|
||||||
|
shouldSuppress = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Reset our count, we've reached our maximum time.
|
||||||
|
_duplicatePacketCount = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Reset our count, it wasn't a duplicate
|
||||||
|
_duplicatePacketCount = 0;
|
||||||
|
}
|
||||||
|
return shouldSuppress;
|
||||||
|
}
|
||||||
|
|
||||||
void VoxelNodeData::resetVoxelPacket() {
|
void VoxelNodeData::resetVoxelPacket() {
|
||||||
|
// Whenever we call this, we will keep a copy of the last packet, so we can determine if the last packet has
|
||||||
|
// changed since we last reset it. Since we know that no two packets can ever be identical without being the same
|
||||||
|
// scene information, (e.g. the root node packet of a static scene), we can use this as a strategy for reducing
|
||||||
|
// packet send rate.
|
||||||
|
_lastVoxelPacketLength = getPacketLength();
|
||||||
|
memcpy(_lastVoxelPacket, _voxelPacket, _lastVoxelPacketLength);
|
||||||
|
|
||||||
// If we're moving, and the client asked for low res, then we force monochrome, otherwise, use
|
// If we're moving, and the client asked for low res, then we force monochrome, otherwise, use
|
||||||
// the clients requested color state.
|
// the clients requested color state.
|
||||||
_currentPacketIsColor = (LOW_RES_MONO && getWantLowResMoving() && _viewFrustumChanging) ? false : getWantColor();
|
_currentPacketIsColor = (LOW_RES_MONO && getWantLowResMoving() && _viewFrustumChanging) ? false : getWantColor();
|
||||||
|
|
|
@ -33,6 +33,10 @@ public:
|
||||||
const unsigned char* getPacket() const { return _voxelPacket; }
|
const unsigned char* getPacket() const { return _voxelPacket; }
|
||||||
int getPacketLength() const { return (MAX_VOXEL_PACKET_SIZE - _voxelPacketAvailableBytes); }
|
int getPacketLength() const { return (MAX_VOXEL_PACKET_SIZE - _voxelPacketAvailableBytes); }
|
||||||
bool isPacketWaiting() const { return _voxelPacketWaiting; }
|
bool isPacketWaiting() const { return _voxelPacketWaiting; }
|
||||||
|
|
||||||
|
bool packetIsDuplicate() const;
|
||||||
|
bool shouldSuppressDuplicatePacket();
|
||||||
|
|
||||||
int getAvailable() const { return _voxelPacketAvailableBytes; }
|
int getAvailable() const { return _voxelPacketAvailableBytes; }
|
||||||
int getMaxSearchLevel() const { return _maxSearchLevel; };
|
int getMaxSearchLevel() const { return _maxSearchLevel; };
|
||||||
void resetMaxSearchLevel() { _maxSearchLevel = 1; };
|
void resetMaxSearchLevel() { _maxSearchLevel = 1; };
|
||||||
|
@ -78,6 +82,12 @@ private:
|
||||||
unsigned char* _voxelPacketAt;
|
unsigned char* _voxelPacketAt;
|
||||||
int _voxelPacketAvailableBytes;
|
int _voxelPacketAvailableBytes;
|
||||||
bool _voxelPacketWaiting;
|
bool _voxelPacketWaiting;
|
||||||
|
|
||||||
|
unsigned char* _lastVoxelPacket;
|
||||||
|
int _lastVoxelPacketLength;
|
||||||
|
int _duplicatePacketCount;
|
||||||
|
uint64_t _firstSuppressedPacket;
|
||||||
|
|
||||||
int _maxSearchLevel;
|
int _maxSearchLevel;
|
||||||
int _maxLevelReachedInLastSearch;
|
int _maxLevelReachedInLastSearch;
|
||||||
ViewFrustum _currentViewFrustum;
|
ViewFrustum _currentViewFrustum;
|
||||||
|
|
|
@ -59,6 +59,14 @@ bool VoxelSendThread::process() {
|
||||||
|
|
||||||
void VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int& trueBytesSent, int& truePacketsSent) {
|
void VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int& trueBytesSent, int& truePacketsSent) {
|
||||||
|
|
||||||
|
// Here's where we check to see if this packet is a duplicate of the last packet. If it is, we will silently
|
||||||
|
// obscure the packet and not send it. This allows the callers and upper level logic to not need to know about
|
||||||
|
// this rate control savings.
|
||||||
|
if (nodeData->shouldSuppressDuplicatePacket()) {
|
||||||
|
printf ("handlePacketSend() silently ate the last packet which was a duplicate...\n");
|
||||||
|
return; // without sending...
|
||||||
|
}
|
||||||
|
|
||||||
// If we've got a stats message ready to send, then see if we can piggyback them together
|
// If we've got a stats message ready to send, then see if we can piggyback them together
|
||||||
if (nodeData->stats.isReadyToSend()) {
|
if (nodeData->stats.isReadyToSend()) {
|
||||||
// Send the stats message to the client
|
// Send the stats message to the client
|
||||||
|
@ -254,13 +262,11 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
||||||
} else {
|
} else {
|
||||||
handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||||
packetsSentThisInterval++;
|
packetsSentThisInterval++;
|
||||||
nodeData->resetVoxelPacket();
|
|
||||||
nodeData->writeToPacket(_tempOutputBuffer, bytesWritten);
|
nodeData->writeToPacket(_tempOutputBuffer, bytesWritten);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (nodeData->isPacketWaiting()) {
|
if (nodeData->isPacketWaiting()) {
|
||||||
handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||||
nodeData->resetVoxelPacket();
|
|
||||||
}
|
}
|
||||||
packetsSentThisInterval = _myServer->getPacketsPerClientPerInterval(); // done for now, no nodes left
|
packetsSentThisInterval = _myServer->getPacketsPerClientPerInterval(); // done for now, no nodes left
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue