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