@@ -153,7 +153,7 @@ pub(crate) struct StreamTxStats {
153
153
/// Can be null in case of missing or bad reports
154
154
rtt : Option < f32 > ,
155
155
/// losses collecter from RR (known packets, lost ratio)
156
- losses : Vec < ( u64 , f32 ) > ,
156
+ losses : Option < Vec < ( u64 , f32 ) > > ,
157
157
158
158
/// `None` if `rtx_ratio_cap` is `None`.
159
159
bytes_transmitted : Option < ValueHistory < u64 > > ,
@@ -162,26 +162,13 @@ pub(crate) struct StreamTxStats {
162
162
bytes_retransmitted : Option < ValueHistory < u64 > > ,
163
163
}
164
164
165
- impl Default for StreamTxStats {
166
- fn default ( ) -> Self {
167
- Self {
168
- bytes : 0 ,
169
- bytes_resent : 0 ,
170
- packets : 0 ,
171
- packets_resent : 0 ,
172
- firs : 0 ,
173
- plis : 0 ,
174
- nacks : 0 ,
175
- rtt : None ,
176
- losses : Vec :: default ( ) ,
177
- bytes_transmitted : Some ( Default :: default ( ) ) ,
178
- bytes_retransmitted : Some ( Default :: default ( ) ) ,
179
- }
180
- }
181
- }
182
-
183
165
impl StreamTx {
184
- pub ( crate ) fn new ( ssrc : Ssrc , rtx : Option < Ssrc > , midrid : MidRid ) -> Self {
166
+ pub ( crate ) fn new (
167
+ ssrc : Ssrc ,
168
+ rtx : Option < Ssrc > ,
169
+ midrid : MidRid ,
170
+ needs_stat_reports : bool ,
171
+ ) -> Self {
185
172
debug ! ( "Create StreamTx for SSRC: {}" , ssrc) ;
186
173
187
174
StreamTx {
@@ -205,7 +192,7 @@ impl StreamTx {
205
192
last_sender_report : already_happened ( ) ,
206
193
pending_request_keyframe : None ,
207
194
pending_request_remb : None ,
208
- stats : StreamTxStats :: default ( ) ,
195
+ stats : StreamTxStats :: new ( needs_stat_reports ) ,
209
196
rtx_ratio : ( 0.0 , already_happened ( ) ) ,
210
197
pt_for_padding : None ,
211
198
remote_acked_ssrc : false ,
@@ -1071,6 +1058,25 @@ impl StreamTx {
1071
1058
}
1072
1059
1073
1060
impl StreamTxStats {
1061
+ fn new ( needs_stat_reports : bool ) -> Self {
1062
+ Self {
1063
+ bytes : 0 ,
1064
+ bytes_resent : 0 ,
1065
+ packets : 0 ,
1066
+ packets_resent : 0 ,
1067
+ firs : 0 ,
1068
+ plis : 0 ,
1069
+ nacks : 0 ,
1070
+ rtt : None ,
1071
+
1072
+ // This Vec is unbounded, don't collect if we're never going to drain it
1073
+ losses : needs_stat_reports. then_some ( Vec :: default ( ) ) ,
1074
+
1075
+ bytes_transmitted : Some ( Default :: default ( ) ) ,
1076
+ bytes_retransmitted : Some ( Default :: default ( ) ) ,
1077
+ }
1078
+ }
1079
+
1074
1080
fn update_packet_counts ( & mut self , bytes : u64 , is_resend : bool ) {
1075
1081
self . packets += 1 ;
1076
1082
self . bytes += bytes;
@@ -1097,41 +1103,42 @@ impl StreamTxStats {
1097
1103
let rtt = calculate_rtt_ms ( ntp_time, r. last_sr_delay , r. last_sr_time ) ;
1098
1104
self . rtt = rtt;
1099
1105
1100
- let ext_seq = {
1101
- let prev = self . losses . last ( ) . map ( |s| s. 0 ) . unwrap_or ( r. max_seq as u64 ) ;
1102
- let next = ( r. max_seq & 0xffff ) as u16 ;
1103
- extend_u16 ( Some ( prev) , next)
1104
- } ;
1106
+ if let Some ( losses) = self . losses . as_mut ( ) {
1107
+ let ext_seq = {
1108
+ let prev = losses. last ( ) . map ( |s| s. 0 ) . unwrap_or ( r. max_seq as u64 ) ;
1109
+ let next = ( r. max_seq & 0xffff ) as u16 ;
1110
+ extend_u16 ( Some ( prev) , next)
1111
+ } ;
1105
1112
1106
- self . losses
1107
- . push ( ( ext_seq , r . fraction_lost as f32 / u8 :: MAX as f32 ) ) ;
1113
+ losses. push ( ( ext_seq , r . fraction_lost as f32 / u8 :: MAX as f32 ) ) ;
1114
+ }
1108
1115
}
1109
1116
1110
1117
pub ( crate ) fn fill ( & mut self , snapshot : & mut StatsSnapshot , midrid : MidRid , now : Instant ) {
1111
1118
if self . bytes == 0 {
1112
1119
return ;
1113
1120
}
1114
1121
1115
- let loss = {
1122
+ let loss = self . losses . as_mut ( ) . and_then ( |losses| {
1116
1123
let mut value = 0_f32 ;
1117
1124
let mut total_weight = 0_u64 ;
1118
1125
1119
1126
// just in case we received RRs out of order
1120
- self . losses . sort_by ( |a, b| a. 0 . partial_cmp ( & b. 0 ) . unwrap ( ) ) ;
1127
+ losses. sort_by ( |a, b| a. 0 . partial_cmp ( & b. 0 ) . unwrap ( ) ) ;
1121
1128
1122
1129
// average known RR losses weighted by their number of packets
1123
- for it in self . losses . windows ( 2 ) {
1130
+ for it in losses. windows ( 2 ) {
1124
1131
let [ prev, next] = it else { continue } ;
1125
1132
let weight = next. 0 . saturating_sub ( prev. 0 ) ;
1126
1133
value += next. 1 * weight as f32 ;
1127
1134
total_weight += weight;
1128
1135
}
1129
1136
1137
+ losses. drain ( ..losses. len ( ) . saturating_sub ( 1 ) ) ;
1138
+
1130
1139
let result = value / total_weight as f32 ;
1131
1140
result. is_finite ( ) . then_some ( result)
1132
- } ;
1133
-
1134
- self . losses . drain ( ..self . losses . len ( ) . saturating_sub ( 1 ) ) ;
1141
+ } ) ;
1135
1142
1136
1143
snapshot. egress . insert (
1137
1144
midrid,
0 commit comments