xref: /aosp_15_r20/external/webrtc/video/send_delay_stats.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "video/send_delay_stats.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <utility>
14*d9f75844SAndroid Build Coastguard Worker 
15*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
16*d9f75844SAndroid Build Coastguard Worker #include "system_wrappers/include/metrics.h"
17*d9f75844SAndroid Build Coastguard Worker 
18*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
19*d9f75844SAndroid Build Coastguard Worker namespace {
20*d9f75844SAndroid Build Coastguard Worker // Packet with a larger delay are removed and excluded from the delay stats.
21*d9f75844SAndroid Build Coastguard Worker // Set to larger than max histogram delay which is 10000.
22*d9f75844SAndroid Build Coastguard Worker const int64_t kMaxSentPacketDelayMs = 11000;
23*d9f75844SAndroid Build Coastguard Worker const size_t kMaxPacketMapSize = 2000;
24*d9f75844SAndroid Build Coastguard Worker 
25*d9f75844SAndroid Build Coastguard Worker // Limit for the maximum number of streams to calculate stats for.
26*d9f75844SAndroid Build Coastguard Worker const size_t kMaxSsrcMapSize = 50;
27*d9f75844SAndroid Build Coastguard Worker const int kMinRequiredPeriodicSamples = 5;
28*d9f75844SAndroid Build Coastguard Worker }  // namespace
29*d9f75844SAndroid Build Coastguard Worker 
SendDelayStats(Clock * clock)30*d9f75844SAndroid Build Coastguard Worker SendDelayStats::SendDelayStats(Clock* clock)
31*d9f75844SAndroid Build Coastguard Worker     : clock_(clock), num_old_packets_(0), num_skipped_packets_(0) {}
32*d9f75844SAndroid Build Coastguard Worker 
~SendDelayStats()33*d9f75844SAndroid Build Coastguard Worker SendDelayStats::~SendDelayStats() {
34*d9f75844SAndroid Build Coastguard Worker   if (num_old_packets_ > 0 || num_skipped_packets_ > 0) {
35*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "Delay stats: number of old packets "
36*d9f75844SAndroid Build Coastguard Worker                         << num_old_packets_ << ", skipped packets "
37*d9f75844SAndroid Build Coastguard Worker                         << num_skipped_packets_ << ". Number of streams "
38*d9f75844SAndroid Build Coastguard Worker                         << send_delay_counters_.size();
39*d9f75844SAndroid Build Coastguard Worker   }
40*d9f75844SAndroid Build Coastguard Worker   UpdateHistograms();
41*d9f75844SAndroid Build Coastguard Worker }
42*d9f75844SAndroid Build Coastguard Worker 
UpdateHistograms()43*d9f75844SAndroid Build Coastguard Worker void SendDelayStats::UpdateHistograms() {
44*d9f75844SAndroid Build Coastguard Worker   MutexLock lock(&mutex_);
45*d9f75844SAndroid Build Coastguard Worker   for (const auto& it : send_delay_counters_) {
46*d9f75844SAndroid Build Coastguard Worker     AggregatedStats stats = it.second->GetStats();
47*d9f75844SAndroid Build Coastguard Worker     if (stats.num_samples >= kMinRequiredPeriodicSamples) {
48*d9f75844SAndroid Build Coastguard Worker       RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.SendDelayInMs", stats.average);
49*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_INFO) << "WebRTC.Video.SendDelayInMs, " << stats.ToString();
50*d9f75844SAndroid Build Coastguard Worker     }
51*d9f75844SAndroid Build Coastguard Worker   }
52*d9f75844SAndroid Build Coastguard Worker }
53*d9f75844SAndroid Build Coastguard Worker 
AddSsrcs(const VideoSendStream::Config & config)54*d9f75844SAndroid Build Coastguard Worker void SendDelayStats::AddSsrcs(const VideoSendStream::Config& config) {
55*d9f75844SAndroid Build Coastguard Worker   MutexLock lock(&mutex_);
56*d9f75844SAndroid Build Coastguard Worker   if (ssrcs_.size() > kMaxSsrcMapSize)
57*d9f75844SAndroid Build Coastguard Worker     return;
58*d9f75844SAndroid Build Coastguard Worker   for (const auto& ssrc : config.rtp.ssrcs)
59*d9f75844SAndroid Build Coastguard Worker     ssrcs_.insert(ssrc);
60*d9f75844SAndroid Build Coastguard Worker }
61*d9f75844SAndroid Build Coastguard Worker 
GetSendDelayCounter(uint32_t ssrc)62*d9f75844SAndroid Build Coastguard Worker AvgCounter* SendDelayStats::GetSendDelayCounter(uint32_t ssrc) {
63*d9f75844SAndroid Build Coastguard Worker   const auto& it = send_delay_counters_.find(ssrc);
64*d9f75844SAndroid Build Coastguard Worker   if (it != send_delay_counters_.end())
65*d9f75844SAndroid Build Coastguard Worker     return it->second.get();
66*d9f75844SAndroid Build Coastguard Worker 
67*d9f75844SAndroid Build Coastguard Worker   AvgCounter* counter = new AvgCounter(clock_, nullptr, false);
68*d9f75844SAndroid Build Coastguard Worker   send_delay_counters_[ssrc].reset(counter);
69*d9f75844SAndroid Build Coastguard Worker   return counter;
70*d9f75844SAndroid Build Coastguard Worker }
71*d9f75844SAndroid Build Coastguard Worker 
OnSendPacket(uint16_t packet_id,int64_t capture_time_ms,uint32_t ssrc)72*d9f75844SAndroid Build Coastguard Worker void SendDelayStats::OnSendPacket(uint16_t packet_id,
73*d9f75844SAndroid Build Coastguard Worker                                   int64_t capture_time_ms,
74*d9f75844SAndroid Build Coastguard Worker                                   uint32_t ssrc) {
75*d9f75844SAndroid Build Coastguard Worker   // Packet sent to transport.
76*d9f75844SAndroid Build Coastguard Worker   MutexLock lock(&mutex_);
77*d9f75844SAndroid Build Coastguard Worker   if (ssrcs_.find(ssrc) == ssrcs_.end())
78*d9f75844SAndroid Build Coastguard Worker     return;
79*d9f75844SAndroid Build Coastguard Worker 
80*d9f75844SAndroid Build Coastguard Worker   int64_t now = clock_->TimeInMilliseconds();
81*d9f75844SAndroid Build Coastguard Worker   RemoveOld(now, &packets_);
82*d9f75844SAndroid Build Coastguard Worker 
83*d9f75844SAndroid Build Coastguard Worker   if (packets_.size() > kMaxPacketMapSize) {
84*d9f75844SAndroid Build Coastguard Worker     ++num_skipped_packets_;
85*d9f75844SAndroid Build Coastguard Worker     return;
86*d9f75844SAndroid Build Coastguard Worker   }
87*d9f75844SAndroid Build Coastguard Worker   packets_.insert(
88*d9f75844SAndroid Build Coastguard Worker       std::make_pair(packet_id, Packet(ssrc, capture_time_ms, now)));
89*d9f75844SAndroid Build Coastguard Worker }
90*d9f75844SAndroid Build Coastguard Worker 
OnSentPacket(int packet_id,int64_t time_ms)91*d9f75844SAndroid Build Coastguard Worker bool SendDelayStats::OnSentPacket(int packet_id, int64_t time_ms) {
92*d9f75844SAndroid Build Coastguard Worker   // Packet leaving socket.
93*d9f75844SAndroid Build Coastguard Worker   if (packet_id == -1)
94*d9f75844SAndroid Build Coastguard Worker     return false;
95*d9f75844SAndroid Build Coastguard Worker 
96*d9f75844SAndroid Build Coastguard Worker   MutexLock lock(&mutex_);
97*d9f75844SAndroid Build Coastguard Worker   auto it = packets_.find(packet_id);
98*d9f75844SAndroid Build Coastguard Worker   if (it == packets_.end())
99*d9f75844SAndroid Build Coastguard Worker     return false;
100*d9f75844SAndroid Build Coastguard Worker 
101*d9f75844SAndroid Build Coastguard Worker   // TODO(asapersson): Remove SendSideDelayUpdated(), use capture -> sent.
102*d9f75844SAndroid Build Coastguard Worker   // Elapsed time from send (to transport) -> sent (leaving socket).
103*d9f75844SAndroid Build Coastguard Worker   int diff_ms = time_ms - it->second.send_time_ms;
104*d9f75844SAndroid Build Coastguard Worker   GetSendDelayCounter(it->second.ssrc)->Add(diff_ms);
105*d9f75844SAndroid Build Coastguard Worker   packets_.erase(it);
106*d9f75844SAndroid Build Coastguard Worker   return true;
107*d9f75844SAndroid Build Coastguard Worker }
108*d9f75844SAndroid Build Coastguard Worker 
RemoveOld(int64_t now,PacketMap * packets)109*d9f75844SAndroid Build Coastguard Worker void SendDelayStats::RemoveOld(int64_t now, PacketMap* packets) {
110*d9f75844SAndroid Build Coastguard Worker   while (!packets->empty()) {
111*d9f75844SAndroid Build Coastguard Worker     auto it = packets->begin();
112*d9f75844SAndroid Build Coastguard Worker     if (now - it->second.capture_time_ms < kMaxSentPacketDelayMs)
113*d9f75844SAndroid Build Coastguard Worker       break;
114*d9f75844SAndroid Build Coastguard Worker 
115*d9f75844SAndroid Build Coastguard Worker     packets->erase(it);
116*d9f75844SAndroid Build Coastguard Worker     ++num_old_packets_;
117*d9f75844SAndroid Build Coastguard Worker   }
118*d9f75844SAndroid Build Coastguard Worker }
119*d9f75844SAndroid Build Coastguard Worker 
120*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
121