Call: prepare receive stats for thread switch.
This change collects the receive stats that Call
maintains into a new thread-compatible
internal class which can easily be switched to
the network thread.
Bug: webrtc:11993
Change-Id: I9fa9a7f057149789aa327e5ba8a8cb3379762272
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/220760
Reviewed-by: Tommi <tommi@webrtc.org>
Commit-Queue: Markus Handell <handellm@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34158}
diff --git a/call/call.cc b/call/call.cc
index f543deb..cdc57be 100644
--- a/call/call.cc
+++ b/call/call.cc
@@ -321,6 +321,37 @@
void SetClientBitratePreferences(const BitrateSettings& preferences) override;
private:
+ // Thread-compatible class that collects received packet stats and exposes
+ // them as UMA histograms on destruction.
+ class ReceiveStats {
+ public:
+ explicit ReceiveStats(Clock* clock);
+ ~ReceiveStats();
+
+ void AddReceivedRtcpBytes(int bytes);
+ void AddReceivedAudioBytes(int bytes, webrtc::Timestamp arrival_time);
+ void AddReceivedVideoBytes(int bytes, webrtc::Timestamp arrival_time);
+
+ private:
+ SequenceChecker sequence_checker_;
+ RateCounter received_bytes_per_second_counter_
+ RTC_GUARDED_BY(sequence_checker_);
+ RateCounter received_audio_bytes_per_second_counter_
+ RTC_GUARDED_BY(sequence_checker_);
+ RateCounter received_video_bytes_per_second_counter_
+ RTC_GUARDED_BY(sequence_checker_);
+ RateCounter received_rtcp_bytes_per_second_counter_
+ RTC_GUARDED_BY(sequence_checker_);
+ absl::optional<Timestamp> first_received_rtp_audio_timestamp_
+ RTC_GUARDED_BY(sequence_checker_);
+ absl::optional<Timestamp> last_received_rtp_audio_timestamp_
+ RTC_GUARDED_BY(sequence_checker_);
+ absl::optional<Timestamp> first_received_rtp_video_timestamp_
+ RTC_GUARDED_BY(sequence_checker_);
+ absl::optional<Timestamp> last_received_rtp_video_timestamp_
+ RTC_GUARDED_BY(sequence_checker_);
+ };
+
DeliveryStatus DeliverRtcp(MediaType media_type,
const uint8_t* packet,
size_t length)
@@ -336,7 +367,6 @@
MediaType media_type)
RTC_SHARED_LOCKS_REQUIRED(worker_thread_);
- void UpdateReceiveHistograms();
void UpdateAggregateNetworkState();
// Ensure that necessary process threads are started, and any required
@@ -433,17 +463,9 @@
webrtc::RtcEventLog* event_log_;
- // The following members are only accessed (exclusively) from one thread and
- // from the destructor, and therefore doesn't need any explicit
- // synchronization.
- RateCounter received_bytes_per_second_counter_;
- RateCounter received_audio_bytes_per_second_counter_;
- RateCounter received_video_bytes_per_second_counter_;
- RateCounter received_rtcp_bytes_per_second_counter_;
- absl::optional<int64_t> first_received_rtp_audio_ms_;
- absl::optional<int64_t> last_received_rtp_audio_ms_;
- absl::optional<int64_t> first_received_rtp_video_ms_;
- absl::optional<int64_t> last_received_rtp_video_ms_;
+ // TODO(bugs.webrtc.org/11993) ready to move receive stats access to the
+ // network thread.
+ ReceiveStats receive_stats_ RTC_GUARDED_BY(worker_thread_);
uint32_t last_bandwidth_bps_ RTC_GUARDED_BY(worker_thread_);
// TODO(holmer): Remove this lock once BitrateController no longer calls
@@ -625,6 +647,94 @@
namespace internal {
+Call::ReceiveStats::ReceiveStats(Clock* clock)
+ : received_bytes_per_second_counter_(clock, nullptr, false),
+ received_audio_bytes_per_second_counter_(clock, nullptr, false),
+ received_video_bytes_per_second_counter_(clock, nullptr, false),
+ received_rtcp_bytes_per_second_counter_(clock, nullptr, false) {
+ sequence_checker_.Detach();
+}
+
+void Call::ReceiveStats::AddReceivedRtcpBytes(int bytes) {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ if (received_bytes_per_second_counter_.HasSample()) {
+ // First RTP packet has been received.
+ received_bytes_per_second_counter_.Add(static_cast<int>(bytes));
+ received_rtcp_bytes_per_second_counter_.Add(static_cast<int>(bytes));
+ }
+}
+
+void Call::ReceiveStats::AddReceivedAudioBytes(int bytes,
+ webrtc::Timestamp arrival_time) {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ received_bytes_per_second_counter_.Add(bytes);
+ received_audio_bytes_per_second_counter_.Add(bytes);
+ if (!first_received_rtp_audio_timestamp_)
+ first_received_rtp_audio_timestamp_ = arrival_time;
+ last_received_rtp_audio_timestamp_ = arrival_time;
+}
+
+void Call::ReceiveStats::AddReceivedVideoBytes(int bytes,
+ webrtc::Timestamp arrival_time) {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ received_bytes_per_second_counter_.Add(bytes);
+ received_video_bytes_per_second_counter_.Add(bytes);
+ if (!first_received_rtp_video_timestamp_)
+ first_received_rtp_video_timestamp_ = arrival_time;
+ last_received_rtp_video_timestamp_ = arrival_time;
+}
+
+Call::ReceiveStats::~ReceiveStats() {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ if (first_received_rtp_audio_timestamp_) {
+ RTC_HISTOGRAM_COUNTS_100000(
+ "WebRTC.Call.TimeReceivingAudioRtpPacketsInSeconds",
+ (*last_received_rtp_audio_timestamp_ -
+ *first_received_rtp_audio_timestamp_)
+ .seconds());
+ }
+ if (first_received_rtp_video_timestamp_) {
+ RTC_HISTOGRAM_COUNTS_100000(
+ "WebRTC.Call.TimeReceivingVideoRtpPacketsInSeconds",
+ (*last_received_rtp_video_timestamp_ -
+ *first_received_rtp_video_timestamp_)
+ .seconds());
+ }
+ const int kMinRequiredPeriodicSamples = 5;
+ AggregatedStats video_bytes_per_sec =
+ received_video_bytes_per_second_counter_.GetStats();
+ if (video_bytes_per_sec.num_samples > kMinRequiredPeriodicSamples) {
+ RTC_HISTOGRAM_COUNTS_100000("WebRTC.Call.VideoBitrateReceivedInKbps",
+ video_bytes_per_sec.average * 8 / 1000);
+ RTC_LOG(LS_INFO) << "WebRTC.Call.VideoBitrateReceivedInBps, "
+ << video_bytes_per_sec.ToStringWithMultiplier(8);
+ }
+ AggregatedStats audio_bytes_per_sec =
+ received_audio_bytes_per_second_counter_.GetStats();
+ if (audio_bytes_per_sec.num_samples > kMinRequiredPeriodicSamples) {
+ RTC_HISTOGRAM_COUNTS_100000("WebRTC.Call.AudioBitrateReceivedInKbps",
+ audio_bytes_per_sec.average * 8 / 1000);
+ RTC_LOG(LS_INFO) << "WebRTC.Call.AudioBitrateReceivedInBps, "
+ << audio_bytes_per_sec.ToStringWithMultiplier(8);
+ }
+ AggregatedStats rtcp_bytes_per_sec =
+ received_rtcp_bytes_per_second_counter_.GetStats();
+ if (rtcp_bytes_per_sec.num_samples > kMinRequiredPeriodicSamples) {
+ RTC_HISTOGRAM_COUNTS_100000("WebRTC.Call.RtcpBitrateReceivedInBps",
+ rtcp_bytes_per_sec.average * 8);
+ RTC_LOG(LS_INFO) << "WebRTC.Call.RtcpBitrateReceivedInBps, "
+ << rtcp_bytes_per_sec.ToStringWithMultiplier(8);
+ }
+ AggregatedStats recv_bytes_per_sec =
+ received_bytes_per_second_counter_.GetStats();
+ if (recv_bytes_per_sec.num_samples > kMinRequiredPeriodicSamples) {
+ RTC_HISTOGRAM_COUNTS_100000("WebRTC.Call.BitrateReceivedInKbps",
+ recv_bytes_per_sec.average * 8 / 1000);
+ RTC_LOG(LS_INFO) << "WebRTC.Call.BitrateReceivedInBps, "
+ << recv_bytes_per_sec.ToStringWithMultiplier(8);
+ }
+}
+
Call::Call(Clock* clock,
const Call::Config& config,
std::unique_ptr<RtpTransportControllerSendInterface> transport_send,
@@ -646,10 +756,7 @@
video_network_state_(kNetworkDown),
aggregate_network_up_(false),
event_log_(config.event_log),
- received_bytes_per_second_counter_(clock_, nullptr, true),
- received_audio_bytes_per_second_counter_(clock_, nullptr, true),
- received_video_bytes_per_second_counter_(clock_, nullptr, true),
- received_rtcp_bytes_per_second_counter_(clock_, nullptr, true),
+ receive_stats_(clock_),
last_bandwidth_bps_(0),
min_allocated_send_bitrate_bps_(0),
configured_max_padding_bitrate_bps_(0),
@@ -710,8 +817,6 @@
pacer_bitrate_kbps_counter_);
}
- UpdateReceiveHistograms();
-
RTC_HISTOGRAM_COUNTS_100000("WebRTC.Call.LifetimeInSeconds",
(now.ms() - start_ms_) / 1000);
}
@@ -737,52 +842,6 @@
GetTransportControllerSend()->SetClientBitratePreferences(preferences);
}
-void Call::UpdateReceiveHistograms() {
- if (first_received_rtp_audio_ms_) {
- RTC_HISTOGRAM_COUNTS_100000(
- "WebRTC.Call.TimeReceivingAudioRtpPacketsInSeconds",
- (*last_received_rtp_audio_ms_ - *first_received_rtp_audio_ms_) / 1000);
- }
- if (first_received_rtp_video_ms_) {
- RTC_HISTOGRAM_COUNTS_100000(
- "WebRTC.Call.TimeReceivingVideoRtpPacketsInSeconds",
- (*last_received_rtp_video_ms_ - *first_received_rtp_video_ms_) / 1000);
- }
- const int kMinRequiredPeriodicSamples = 5;
- AggregatedStats video_bytes_per_sec =
- received_video_bytes_per_second_counter_.GetStats();
- if (video_bytes_per_sec.num_samples > kMinRequiredPeriodicSamples) {
- RTC_HISTOGRAM_COUNTS_100000("WebRTC.Call.VideoBitrateReceivedInKbps",
- video_bytes_per_sec.average * 8 / 1000);
- RTC_LOG(LS_INFO) << "WebRTC.Call.VideoBitrateReceivedInBps, "
- << video_bytes_per_sec.ToStringWithMultiplier(8);
- }
- AggregatedStats audio_bytes_per_sec =
- received_audio_bytes_per_second_counter_.GetStats();
- if (audio_bytes_per_sec.num_samples > kMinRequiredPeriodicSamples) {
- RTC_HISTOGRAM_COUNTS_100000("WebRTC.Call.AudioBitrateReceivedInKbps",
- audio_bytes_per_sec.average * 8 / 1000);
- RTC_LOG(LS_INFO) << "WebRTC.Call.AudioBitrateReceivedInBps, "
- << audio_bytes_per_sec.ToStringWithMultiplier(8);
- }
- AggregatedStats rtcp_bytes_per_sec =
- received_rtcp_bytes_per_second_counter_.GetStats();
- if (rtcp_bytes_per_sec.num_samples > kMinRequiredPeriodicSamples) {
- RTC_HISTOGRAM_COUNTS_100000("WebRTC.Call.RtcpBitrateReceivedInBps",
- rtcp_bytes_per_sec.average * 8);
- RTC_LOG(LS_INFO) << "WebRTC.Call.RtcpBitrateReceivedInBps, "
- << rtcp_bytes_per_sec.ToStringWithMultiplier(8);
- }
- AggregatedStats recv_bytes_per_sec =
- received_bytes_per_second_counter_.GetStats();
- if (recv_bytes_per_sec.num_samples > kMinRequiredPeriodicSamples) {
- RTC_HISTOGRAM_COUNTS_100000("WebRTC.Call.BitrateReceivedInKbps",
- recv_bytes_per_sec.average * 8 / 1000);
- RTC_LOG(LS_INFO) << "WebRTC.Call.BitrateReceivedInBps, "
- << recv_bytes_per_sec.ToStringWithMultiplier(8);
- }
-}
-
PacketReceiver* Call::Receiver() {
return this;
}
@@ -1381,11 +1440,7 @@
// TODO(pbos): Make sure it's a valid packet.
// Return DELIVERY_UNKNOWN_SSRC if it can be determined that
// there's no receiver of the packet.
- if (received_bytes_per_second_counter_.HasSample()) {
- // First RTP packet has been received.
- received_bytes_per_second_counter_.Add(static_cast<int>(length));
- received_rtcp_bytes_per_second_counter_.Add(static_cast<int>(length));
- }
+ receive_stats_.AddReceivedRtcpBytes(static_cast<int>(length));
bool rtcp_delivered = false;
if (media_type == MediaType::ANY || media_type == MediaType::VIDEO) {
for (VideoReceiveStream2* stream : video_receive_streams_) {
@@ -1471,29 +1526,19 @@
int length = static_cast<int>(parsed_packet.size());
if (media_type == MediaType::AUDIO) {
if (audio_receiver_controller_.OnRtpPacket(parsed_packet)) {
- received_bytes_per_second_counter_.Add(length);
- received_audio_bytes_per_second_counter_.Add(length);
+ receive_stats_.AddReceivedAudioBytes(length,
+ parsed_packet.arrival_time());
event_log_->Log(
std::make_unique<RtcEventRtpPacketIncoming>(parsed_packet));
- const int64_t arrival_time_ms = parsed_packet.arrival_time().ms();
- if (!first_received_rtp_audio_ms_) {
- first_received_rtp_audio_ms_.emplace(arrival_time_ms);
- }
- last_received_rtp_audio_ms_.emplace(arrival_time_ms);
return DELIVERY_OK;
}
} else if (media_type == MediaType::VIDEO) {
parsed_packet.set_payload_type_frequency(kVideoPayloadTypeFrequency);
if (video_receiver_controller_.OnRtpPacket(parsed_packet)) {
- received_bytes_per_second_counter_.Add(length);
- received_video_bytes_per_second_counter_.Add(length);
+ receive_stats_.AddReceivedVideoBytes(length,
+ parsed_packet.arrival_time());
event_log_->Log(
std::make_unique<RtcEventRtpPacketIncoming>(parsed_packet));
- const int64_t arrival_time_ms = parsed_packet.arrival_time().ms();
- if (!first_received_rtp_video_ms_) {
- first_received_rtp_video_ms_.emplace(arrival_time_ms);
- }
- last_received_rtp_video_ms_.emplace(arrival_time_ms);
return DELIVERY_OK;
}
}