Overte C++ Documentation
AvatarMixerSlave.h
1 //
2 // AvatarMixerSlave.h
3 // assignment-client/src/avatar
4 //
5 // Created by Brad Hefta-Gaub on 2/14/2017.
6 // Copyright 2017 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_AvatarMixerSlave_h
13 #define hifi_AvatarMixerSlave_h
14 
15 #include <NodeList.h>
16 
17 class AvatarMixerClientData;
18 
19 class AvatarMixerSlaveStats {
20 public:
21  int nodesProcessed { 0 };
22  int packetsProcessed { 0 };
23  quint64 processIncomingPacketsElapsedTime { 0 };
24 
25  int nodesBroadcastedTo { 0 };
26  int downstreamMixersBroadcastedTo { 0 };
27  int numDataBytesSent { 0 };
28  int numTraitsBytesSent { 0 };
29  int numIdentityBytesSent { 0 };
30  int numDataPacketsSent { 0 };
31  int numTraitsPacketsSent { 0 };
32  int numIdentityPacketsSent { 0 };
33  int numOthersIncluded { 0 };
34  int overBudgetAvatars { 0 };
35  int numHeroesIncluded { 0 };
36 
37  quint64 ignoreCalculationElapsedTime { 0 };
38  quint64 avatarDataPackingElapsedTime { 0 };
39  quint64 packetSendingElapsedTime { 0 };
40  quint64 toByteArrayElapsedTime { 0 };
41  quint64 jobElapsedTime { 0 };
42 
43  void reset() {
44  // receiving job stats
45  nodesProcessed = 0;
46  packetsProcessed = 0;
47  processIncomingPacketsElapsedTime = 0;
48 
49  // sending job stats
50  nodesBroadcastedTo = 0;
51  downstreamMixersBroadcastedTo = 0;
52 
53  numDataBytesSent = 0;
54  numTraitsBytesSent = 0;
55  numIdentityBytesSent = 0;
56  numDataPacketsSent = 0;
57  numTraitsPacketsSent = 0;
58  numIdentityPacketsSent = 0;
59  numOthersIncluded = 0;
60  overBudgetAvatars = 0;
61  numHeroesIncluded = 0;
62 
63  ignoreCalculationElapsedTime = 0;
64  avatarDataPackingElapsedTime = 0;
65  packetSendingElapsedTime = 0;
66  toByteArrayElapsedTime = 0;
67  jobElapsedTime = 0;
68  }
69 
70  AvatarMixerSlaveStats& operator+=(const AvatarMixerSlaveStats& rhs) {
71  nodesProcessed += rhs.nodesProcessed;
72  packetsProcessed += rhs.packetsProcessed;
73  processIncomingPacketsElapsedTime += rhs.processIncomingPacketsElapsedTime;
74 
75  nodesBroadcastedTo += rhs.nodesBroadcastedTo;
76  downstreamMixersBroadcastedTo += rhs.downstreamMixersBroadcastedTo;
77  numDataBytesSent += rhs.numDataBytesSent;
78  numTraitsBytesSent += rhs.numTraitsBytesSent;
79  numIdentityBytesSent += rhs.numIdentityBytesSent;
80  numDataPacketsSent += rhs.numDataPacketsSent;
81  numTraitsPacketsSent += rhs.numTraitsPacketsSent;
82  numIdentityPacketsSent += rhs.numIdentityPacketsSent;
83  numOthersIncluded += rhs.numOthersIncluded;
84  overBudgetAvatars += rhs.overBudgetAvatars;
85  numHeroesIncluded += rhs.numHeroesIncluded;
86 
87  ignoreCalculationElapsedTime += rhs.ignoreCalculationElapsedTime;
88  avatarDataPackingElapsedTime += rhs.avatarDataPackingElapsedTime;
89  packetSendingElapsedTime += rhs.packetSendingElapsedTime;
90  toByteArrayElapsedTime += rhs.toByteArrayElapsedTime;
91  jobElapsedTime += rhs.jobElapsedTime;
92  return *this;
93  }
94 };
95 
96 class EntityTree;
97 using EntityTreePointer = std::shared_ptr<EntityTree>;
98 
99 struct SlaveSharedData {
100  QStringList skeletonURLWhitelist;
101  QUrl skeletonReplacementURL;
102  EntityTreePointer entityTree;
103 };
104 
105 class AvatarMixerSlave {
106 public:
107  AvatarMixerSlave(SlaveSharedData* sharedData) : _sharedData(sharedData) {};
108  using ConstIter = NodeList::const_iterator;
109 
110  void configure(ConstIter begin, ConstIter end);
111  void configureBroadcast(ConstIter begin, ConstIter end,
112  p_high_resolution_clock::time_point lastFrameTimestamp,
113  float maxKbpsPerNode, float throttlingRatio,
114  float priorityReservedFraction);
115 
116  void processIncomingPackets(const SharedNodePointer& node);
117  void broadcastAvatarData(const SharedNodePointer& node);
118 
119  void harvestStats(AvatarMixerSlaveStats& stats);
120 
121 private:
122  int sendIdentityPacket(NLPacketList& packet, const AvatarMixerClientData* nodeData, const Node& destinationNode);
123  int sendReplicatedIdentityPacket(const Node& agentNode, const AvatarMixerClientData* nodeData, const Node& destinationNode);
124 
125  qint64 addTraitsNodeHeader(AvatarMixerClientData* listeningNodeData,
126  const AvatarMixerClientData* sendingNodeData,
127  NLPacketList& traitsPacketList,
128  qint64 bytesWritten);
129 
130  qint64 addChangedTraitsToBulkPacket(AvatarMixerClientData* listeningNodeData,
131  const AvatarMixerClientData* sendingNodeData,
132  NLPacketList& traitsPacketList);
133 
134  void broadcastAvatarDataToAgent(const SharedNodePointer& node);
135  void broadcastAvatarDataToDownstreamMixer(const SharedNodePointer& node);
136 
137  // frame state
138  ConstIter _begin;
139  ConstIter _end;
140 
141  p_high_resolution_clock::time_point _lastFrameTimestamp;
142  float _maxKbpsPerNode { 0.0f };
143  float _throttlingRatio { 0.0f };
144  float _avatarHeroFraction { 0.4f };
145 
146  AvatarMixerSlaveStats _stats;
147  SlaveSharedData* _sharedData;
148 };
149 
150 #endif // hifi_AvatarMixerSlave_h