Overte C++ Documentation
AvatarMixerClientData.h
1 //
2 // AvatarMixerClientData.h
3 // assignment-client/src/avatars
4 //
5 // Created by Stephen Birarda on 2/4/2014.
6 // Copyright 2014 High Fidelity, Inc.
7 //
8 // Distributed under the Apache License, Version 2.0.
9 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10 //
11 
12 #ifndef hifi_AvatarMixerClientData_h
13 #define hifi_AvatarMixerClientData_h
14 
15 #include <algorithm>
16 #include <cfloat>
17 #include <unordered_map>
18 #include <vector>
19 #include <queue>
20 
21 #include <QtCore/QJsonObject>
22 #include <QtCore/QSharedPointer>
23 #include <QtCore/QUrl>
24 
25 #include "MixerAvatar.h"
26 #include <AssociatedTraitValues.h>
27 #include <NodeData.h>
28 #include <NumericalConstants.h>
29 #include <udt/PacketHeaders.h>
30 #include <PortableHighResolutionClock.h>
31 #include <SimpleMovingAverage.h>
32 #include <UUIDHasher.h>
33 #include <shared/ConicalViewFrustum.h>
34 
35 const QString OUTBOUND_AVATAR_DATA_STATS_KEY = "outbound_av_data_kbps";
36 const QString OUTBOUND_AVATAR_TRAITS_STATS_KEY = "outbound_av_traits_kbps";
37 const QString INBOUND_AVATAR_DATA_STATS_KEY = "inbound_av_data_kbps";
38 
39 struct SlaveSharedData;
40 
41 class AvatarMixerClientData : public NodeData {
42  Q_OBJECT
43 public:
44  AvatarMixerClientData(const QUuid& nodeID, Node::LocalID nodeLocalID);
45  virtual ~AvatarMixerClientData() {}
46  using HRCTime = p_high_resolution_clock::time_point;
47  using PerNodeTraitVersions = std::unordered_map<Node::LocalID, AvatarTraits::TraitVersions>;
48 
49  using NodeData::parseData; // Avoid clang warning about hiding.
50  int parseData(ReceivedMessage& message, const SlaveSharedData& SlaveSharedData);
51  MixerAvatar& getAvatar() { return *_avatar; }
52  const MixerAvatar& getAvatar() const { return *_avatar; }
53  const MixerAvatar* getConstAvatarData() const { return _avatar.get(); }
54  MixerAvatarSharedPointer getAvatarSharedPointer() const { return _avatar; }
55 
56  uint16_t getLastBroadcastSequenceNumber(NLPacket::LocalID nodeID) const;
57  void setLastBroadcastSequenceNumber(NLPacket::LocalID nodeID, uint16_t sequenceNumber)
58  { _lastBroadcastSequenceNumbers[nodeID] = sequenceNumber; }
59  Q_INVOKABLE void removeLastBroadcastSequenceNumber(NLPacket::LocalID nodeID) { _lastBroadcastSequenceNumbers.erase(nodeID); }
60  bool isIgnoreRadiusEnabled() const { return _isIgnoreRadiusEnabled; }
61  void setIsIgnoreRadiusEnabled(bool enabled) { _isIgnoreRadiusEnabled = enabled; }
62 
63  uint64_t getLastBroadcastTime(NLPacket::LocalID nodeUUID) const;
64  void setLastBroadcastTime(NLPacket::LocalID nodeUUID, uint64_t broadcastTime) { _lastBroadcastTimes[nodeUUID] = broadcastTime; }
65  Q_INVOKABLE void removeLastBroadcastTime(NLPacket::LocalID nodeUUID) { _lastBroadcastTimes.erase(nodeUUID); }
66 
67  Q_INVOKABLE void cleanupKilledNode(const QUuid& nodeUUID, Node::LocalID nodeLocalID);
68 
69  uint16_t getLastReceivedSequenceNumber() const { return _lastReceivedSequenceNumber; }
70 
71  uint64_t getIdentityChangeTimestamp() const { return _identityChangeTimestamp; }
72  void flagIdentityChange() { _identityChangeTimestamp = usecTimestampNow(); }
73  bool getAvatarSessionDisplayNameMustChange() const { return _avatarSessionDisplayNameMustChange; }
74  void setAvatarSessionDisplayNameMustChange(bool set = true) { _avatarSessionDisplayNameMustChange = set; }
75 
76  void resetNumAvatarsSentLastFrame() { _numAvatarsSentLastFrame = 0; }
77  void incrementNumAvatarsSentLastFrame() { ++_numAvatarsSentLastFrame; }
78  int getNumAvatarsSentLastFrame() const { return _numAvatarsSentLastFrame; }
79 
80  void recordNumOtherAvatarStarves(int numAvatarsHeldBack) { _otherAvatarStarves.updateAverage((float) numAvatarsHeldBack); }
81  float getAvgNumOtherAvatarStarvesPerSecond() const { return _otherAvatarStarves.getAverageSampleValuePerSecond(); }
82 
83  void recordNumOtherAvatarSkips(int numOtherAvatarSkips) { _otherAvatarSkips.updateAverage((float) numOtherAvatarSkips); }
84  float getAvgNumOtherAvatarSkipsPerSecond() const { return _otherAvatarSkips.getAverageSampleValuePerSecond(); }
85 
86  void incrementNumOutOfOrderSends() { ++_numOutOfOrderSends; }
87 
88  int getNumFramesSinceFRDAdjustment() const { return _numFramesSinceAdjustment; }
89  void incrementNumFramesSinceFRDAdjustment() { ++_numFramesSinceAdjustment; }
90  void resetNumFramesSinceFRDAdjustment() { _numFramesSinceAdjustment = 0; }
91 
92  void recordSentAvatarData(int numDataBytes, int numTraitsBytes = 0) {
93  _avgOtherAvatarDataRate.updateAverage(numDataBytes);
94  _avgOtherAvatarTraitsRate.updateAverage(numTraitsBytes);
95  }
96 
97  float getOutboundAvatarDataKbps() const
98  { return _avgOtherAvatarDataRate.getAverageSampleValuePerSecond() / (float) BYTES_PER_KILOBIT; }
99  float getOutboundAvatarTraitsKbps() const
100  { return _avgOtherAvatarTraitsRate.getAverageSampleValuePerSecond() / BYTES_PER_KILOBIT; }
101 
102  void loadJSONStats(QJsonObject& jsonObject) const;
103 
104  glm::vec3 getPosition() const { return _avatar ? _avatar->getClientGlobalPosition() : glm::vec3(0); }
105  bool isRadiusIgnoring(const QUuid& other) const;
106  void addToRadiusIgnoringSet(const QUuid& other);
107  void removeFromRadiusIgnoringSet(const QUuid& other);
108  void ignoreOther(SharedNodePointer self, SharedNodePointer other);
109  void ignoreOther(const Node* self, const Node* other);
110 
111  void readViewFrustumPacket(const QByteArray& message);
112 
113  bool otherAvatarInView(const AABox& otherAvatarBox);
114 
115  void resetInViewStats() { _recentOtherAvatarsInView = _recentOtherAvatarsOutOfView = 0; }
116  void incrementAvatarInView() { _recentOtherAvatarsInView++; }
117  void incrementAvatarOutOfView() { _recentOtherAvatarsOutOfView++; }
118  const QString& getBaseDisplayName() { return _baseDisplayName; }
119  void setBaseDisplayName(const QString& baseDisplayName) { _baseDisplayName = baseDisplayName; }
120  bool getRequestsDomainListData() { return _requestsDomainListData; }
121  void setRequestsDomainListData(bool requesting) { _requestsDomainListData = requesting; }
122  bool getPrevRequestsDomainListData() { return _prevRequestsDomainListData; }
123  void setPrevRequestsDomainListData(bool requesting) { _prevRequestsDomainListData = requesting; }
124 
125  const ConicalViewFrustums& getViewFrustums() const { return _currentViewFrustums; }
126 
127  uint64_t getLastOtherAvatarEncodeTime(NLPacket::LocalID otherAvatar) const;
128  void setLastOtherAvatarEncodeTime(NLPacket::LocalID otherAvatar, uint64_t time);
129 
130  QVector<JointData>& getLastOtherAvatarSentJoints(NLPacket::LocalID otherAvatar) { return _lastOtherAvatarSentJoints[otherAvatar]; }
131 
132  void queuePacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer node);
133  int processPackets(const SlaveSharedData& slaveSharedData); // returns number of packets processed
134 
135  void processSetTraitsMessage(ReceivedMessage& message, const SlaveSharedData& slaveSharedData, Node& sendingNode);
136  void emulateDeleteEntitiesTraitsMessage(const QList<QUuid>& avatarEntityIDs);
137  void processBulkAvatarTraitsAckMessage(ReceivedMessage& message);
138  void checkSkeletonURLAgainstWhitelist(const SlaveSharedData& slaveSharedData, Node& sendingNode,
139  AvatarTraits::TraitVersion traitVersion);
140 
141  using TraitsCheckTimestamp = std::chrono::steady_clock::time_point;
142 
143  TraitsCheckTimestamp getLastReceivedTraitsChange() const { return _lastReceivedTraitsChange; }
144 
145  AvatarTraits::TraitVersions& getLastReceivedTraitVersions() { return _lastReceivedTraitVersions; }
146  const AvatarTraits::TraitVersions& getLastReceivedTraitVersions() const { return _lastReceivedTraitVersions; }
147 
148  TraitsCheckTimestamp getLastOtherAvatarTraitsSendPoint(Node::LocalID otherAvatar) const;
149  void setLastOtherAvatarTraitsSendPoint(Node::LocalID otherAvatar, TraitsCheckTimestamp sendPoint)
150  { _lastSentTraitsTimestamps[otherAvatar] = sendPoint; }
151 
152  AvatarTraits::TraitMessageSequence getTraitsMessageSequence() const { return _currentTraitsMessageSequence; }
153  AvatarTraits::TraitMessageSequence nextTraitsMessageSequence() { return ++_currentTraitsMessageSequence; }
154  AvatarTraits::TraitVersions& getPendingTraitVersions(AvatarTraits::TraitMessageSequence seq, Node::LocalID otherId) {
155  return _perNodePendingTraitVersions[seq][otherId];
156  }
157 
158  AvatarTraits::TraitVersions& getLastSentTraitVersions(Node::LocalID otherAvatar) { return _perNodeSentTraitVersions[otherAvatar]; }
159  AvatarTraits::TraitVersions& getLastAckedTraitVersions(Node::LocalID otherAvatar) { return _perNodeAckedTraitVersions[otherAvatar]; }
160 
161  void resetSentTraitData(Node::LocalID nodeID);
162 
163 private:
164  struct PacketQueue : public std::queue<QSharedPointer<ReceivedMessage>> {
165  QWeakPointer<Node> node;
166  };
167  PacketQueue _packetQueue;
168 
169  MixerAvatarSharedPointer _avatar { new MixerAvatar() };
170 
171  uint16_t _lastReceivedSequenceNumber { 0 };
172  std::unordered_map<NLPacket::LocalID, uint16_t> _lastBroadcastSequenceNumbers;
173  std::unordered_map<NLPacket::LocalID, uint64_t> _lastBroadcastTimes;
174 
175  // this is a map of the last time we encoded an "other" avatar for
176  // sending to "this" node
177  std::unordered_map<NLPacket::LocalID, uint64_t> _lastOtherAvatarEncodeTime;
178  std::unordered_map<NLPacket::LocalID, QVector<JointData>> _lastOtherAvatarSentJoints;
179 
180  uint64_t _identityChangeTimestamp;
181  bool _avatarSessionDisplayNameMustChange{ true };
182  bool _avatarSkeletonModelUrlMustChange{ false };
183 
184  int _numAvatarsSentLastFrame = 0;
185  int _numFramesSinceAdjustment = 0;
186 
187  SimpleMovingAverage _otherAvatarStarves;
188  SimpleMovingAverage _otherAvatarSkips;
189  int _numOutOfOrderSends = 0;
190 
191  SimpleMovingAverage _avgOtherAvatarDataRate;
192  SimpleMovingAverage _avgOtherAvatarTraitsRate;
193  std::vector<QUuid> _radiusIgnoredOthers;
194  ConicalViewFrustums _currentViewFrustums;
195 
196  int _recentOtherAvatarsInView { 0 };
197  int _recentOtherAvatarsOutOfView { 0 };
198  QString _baseDisplayName{}; // The santized key used in determinging unique sessionDisplayName, so that we can remove from dictionary.
199  bool _requestsDomainListData { false };
200  bool _prevRequestsDomainListData{ false };
201 
202  AvatarTraits::TraitVersions _lastReceivedTraitVersions;
203  TraitsCheckTimestamp _lastReceivedTraitsChange;
204 
205  AvatarTraits::TraitMessageSequence _currentTraitsMessageSequence{ 0 };
206 
207  // Cache of trait versions sent in a given packet (indexed by sequence number)
208  // When an ack is received, the sequence number in the ack is used to look up
209  // the sent trait versions and they are copied to _perNodeAckedTraitVersions.
210  // We remember the data in _perNodePendingTraitVersions instead of requiring
211  // the client to return all of the versions for each trait it received in a given packet,
212  // reducing the size of the ack packet.
213  std::unordered_map<AvatarTraits::TraitMessageSequence, PerNodeTraitVersions> _perNodePendingTraitVersions;
214 
215  // Versions of traits that have been acked, which will be compared to incoming
216  // trait updates. Incoming updates going to a given node will be ignored if
217  // the ack for the previous packet (containing those versions) has not been
218  // received.
219  PerNodeTraitVersions _perNodeAckedTraitVersions;
220 
221  std::unordered_map<Node::LocalID, TraitsCheckTimestamp> _lastSentTraitsTimestamps;
222 
223  // cache of traits sent to a node which are compared to incoming traits to
224  // prevent sending traits that have already been sent.
225  PerNodeTraitVersions _perNodeSentTraitVersions;
226 
227  std::atomic_bool _isIgnoreRadiusEnabled { false };
228 };
229 
230 #endif // hifi_AvatarMixerClientData_h