Add resolution and fps stats to histograms:
- "WebRTC.Video.InputWidthInPixels"
- "WebRTC.Video.InputHeightInPixels"
- "WebRTC.Video.SentWidthInPixels"
- "WebRTC.Video.SentHeightInPixels"
- "WebRTC.Video.ReceivedWidthInPixels"
- "WebRTC.Video.ReceivedHeightInPixels"
- "WebRTC.Video.RenderFramesPerSecond"
BUG=chromium:512752
Review URL: https://codereview.webrtc.org/1228393008
Cr-Commit-Position: refs/heads/master@{#9611}
diff --git a/webrtc/test/fake_encoder.cc b/webrtc/test/fake_encoder.cc
index 3a80b98..a840ddb 100644
--- a/webrtc/test/fake_encoder.cc
+++ b/webrtc/test/fake_encoder.cc
@@ -97,6 +97,8 @@
encoded._timeStamp = input_image.timestamp();
encoded.capture_time_ms_ = input_image.render_time_ms();
encoded._frameType = (*frame_types)[i];
+ encoded._encodedWidth = config_.simulcastStream[i].width;
+ encoded._encodedHeight = config_.simulcastStream[i].height;
// Always encode something on the first frame.
if (min_stream_bits > bits_available && i > 0) {
encoded._length = 0;
diff --git a/webrtc/video/end_to_end_tests.cc b/webrtc/video/end_to_end_tests.cc
index ab4dfaf..33fc75e 100644
--- a/webrtc/video/end_to_end_tests.cc
+++ b/webrtc/video/end_to_end_tests.cc
@@ -1634,10 +1634,32 @@
EXPECT_EQ(1, test::NumHistogramSamples(
"WebRTC.Video.ReceivedPacketsLostInPercent"));
+ EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.InputWidthInPixels"));
+ EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.InputHeightInPixels"));
+ EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.SentWidthInPixels"));
+ EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.SentHeightInPixels"));
+ EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.ReceivedWidthInPixels"));
+ EXPECT_EQ(1,
+ test::NumHistogramSamples("WebRTC.Video.ReceivedHeightInPixels"));
+
+ EXPECT_EQ(static_cast<int>(encoder_config_.streams[0].width),
+ test::LastHistogramSample("WebRTC.Video.InputWidthInPixels"));
+ EXPECT_EQ(static_cast<int>(encoder_config_.streams[0].height),
+ test::LastHistogramSample("WebRTC.Video.InputHeightInPixels"));
+ EXPECT_EQ(static_cast<int>(encoder_config_.streams[0].width),
+ test::LastHistogramSample("WebRTC.Video.SentWidthInPixels"));
+ EXPECT_EQ(static_cast<int>(encoder_config_.streams[0].height),
+ test::LastHistogramSample("WebRTC.Video.SentHeightInPixels"));
+ EXPECT_EQ(static_cast<int>(encoder_config_.streams[0].width),
+ test::LastHistogramSample("WebRTC.Video.ReceivedWidthInPixels"));
+ EXPECT_EQ(static_cast<int>(encoder_config_.streams[0].height),
+ test::LastHistogramSample("WebRTC.Video.ReceivedHeightInPixels"));
+
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.InputFramesPerSecond"));
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.SentFramesPerSecond"));
EXPECT_EQ(1, test::NumHistogramSamples(
"WebRTC.Video.DecodedFramesPerSecond"));
+ EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.RenderFramesPerSecond"));
EXPECT_EQ(1, test::NumHistogramSamples(
"WebRTC.Video.BitrateSentInKbps"));
diff --git a/webrtc/video/receive_statistics_proxy.cc b/webrtc/video/receive_statistics_proxy.cc
index b5d8056..e028dab 100644
--- a/webrtc/video/receive_statistics_proxy.cc
+++ b/webrtc/video/receive_statistics_proxy.cc
@@ -28,16 +28,24 @@
UpdateHistograms();
}
-void ReceiveStatisticsProxy::UpdateHistograms() const {
- int fraction_lost;
- {
- rtc::CritScope lock(&crit_);
- fraction_lost = report_block_stats_.FractionLostInPercent();
- }
+void ReceiveStatisticsProxy::UpdateHistograms() {
+ int fraction_lost = report_block_stats_.FractionLostInPercent();
if (fraction_lost != -1) {
RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.ReceivedPacketsLostInPercent",
fraction_lost);
}
+
+ int render_fps = static_cast<int>(render_fps_tracker_total_.units_second());
+ if (render_fps > 0)
+ RTC_HISTOGRAM_COUNTS_100("WebRTC.Video.RenderFramesPerSecond", render_fps);
+
+ const int kMinRequiredSamples = 100;
+ int width = render_width_counter_.Avg(kMinRequiredSamples);
+ int height = render_height_counter_.Avg(kMinRequiredSamples);
+ if (width != -1) {
+ RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.ReceivedWidthInPixels", width);
+ RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.ReceivedHeightInPixels", height);
+ }
}
VideoReceiveStream::Stats ReceiveStatisticsProxy::GetStats() const {
@@ -117,12 +125,15 @@
stats_.decode_frame_rate = decode_fps_estimator_.Rate(now);
}
-void ReceiveStatisticsProxy::OnRenderedFrame() {
+void ReceiveStatisticsProxy::OnRenderedFrame(int width, int height) {
uint64_t now = clock_->TimeInMilliseconds();
rtc::CritScope lock(&crit_);
renders_fps_estimator_.Update(1, now);
stats_.render_frame_rate = renders_fps_estimator_.Rate(now);
+ render_width_counter_.Add(width);
+ render_height_counter_.Add(height);
+ render_fps_tracker_total_.Update(1);
}
void ReceiveStatisticsProxy::OnReceiveRatesUpdated(uint32_t bitRate,
@@ -140,4 +151,15 @@
stats_.discarded_packets = discarded_packets;
}
+void ReceiveStatisticsProxy::SampleCounter::Add(int sample) {
+ sum += sample;
+ ++num_samples;
+}
+
+int ReceiveStatisticsProxy::SampleCounter::Avg(int min_required_samples) const {
+ if (num_samples < min_required_samples || num_samples == 0)
+ return -1;
+ return sum / num_samples;
+}
+
} // namespace webrtc
diff --git a/webrtc/video/receive_statistics_proxy.h b/webrtc/video/receive_statistics_proxy.h
index df763ad..0d22948 100644
--- a/webrtc/video/receive_statistics_proxy.h
+++ b/webrtc/video/receive_statistics_proxy.h
@@ -14,6 +14,7 @@
#include <string>
#include "webrtc/base/criticalsection.h"
+#include "webrtc/base/ratetracker.h"
#include "webrtc/base/thread_annotations.h"
#include "webrtc/common_types.h"
#include "webrtc/frame_callback.h"
@@ -42,9 +43,9 @@
VideoReceiveStream::Stats GetStats() const;
void OnDecodedFrame();
- void OnRenderedFrame();
+ void OnRenderedFrame(int width, int height);
- // Overrides VCMReceiveStatisticsCallback
+ // Overrides VCMReceiveStatisticsCallback.
void OnReceiveRatesUpdated(uint32_t bitRate, uint32_t frameRate) override;
void OnFrameCountsUpdated(const FrameCounts& frame_counts) override;
void OnDiscardedPacketsUpdated(int discarded_packets) override;
@@ -68,7 +69,7 @@
uint32_t ssrc) override;
void CNameChanged(const char* cname, uint32_t ssrc) override;
- // Overrides RtcpPacketTypeCounterObserver
+ // Overrides RtcpPacketTypeCounterObserver.
void RtcpPacketTypesCounterUpdated(
uint32_t ssrc,
const RtcpPacketTypeCounter& packet_counter) override;
@@ -77,13 +78,27 @@
uint32_t ssrc) override;
private:
- void UpdateHistograms() const;
+ struct SampleCounter {
+ SampleCounter() : sum(0), num_samples(0) {}
+ void Add(int sample);
+ int Avg(int min_required_samples) const;
+
+ private:
+ int sum;
+ int num_samples;
+ };
+
+ void UpdateHistograms() EXCLUSIVE_LOCKS_REQUIRED(crit_);
+
Clock* const clock_;
mutable rtc::CriticalSection crit_;
VideoReceiveStream::Stats stats_ GUARDED_BY(crit_);
RateStatistics decode_fps_estimator_ GUARDED_BY(crit_);
RateStatistics renders_fps_estimator_ GUARDED_BY(crit_);
+ rtc::RateTracker render_fps_tracker_total_ GUARDED_BY(crit_);
+ SampleCounter render_width_counter_ GUARDED_BY(crit_);
+ SampleCounter render_height_counter_ GUARDED_BY(crit_);
ReportBlockStats report_block_stats_ GUARDED_BY(crit_);
};
diff --git a/webrtc/video/send_statistics_proxy.cc b/webrtc/video/send_statistics_proxy.cc
index c6f48e2..fe60f1e 100644
--- a/webrtc/video/send_statistics_proxy.cc
+++ b/webrtc/video/send_statistics_proxy.cc
@@ -10,6 +10,7 @@
#include "webrtc/video/send_statistics_proxy.h"
+#include <algorithm>
#include <map>
#include "webrtc/base/checks.h"
@@ -24,7 +25,11 @@
SendStatisticsProxy::SendStatisticsProxy(Clock* clock,
const VideoSendStream::Config& config)
- : clock_(clock), config_(config), last_sent_frame_timestamp_(0) {
+ : clock_(clock),
+ config_(config),
+ last_sent_frame_timestamp_(0),
+ max_sent_width_per_timestamp_(0),
+ max_sent_height_per_timestamp_(0) {
}
SendStatisticsProxy::~SendStatisticsProxy() {
@@ -34,13 +39,26 @@
void SendStatisticsProxy::UpdateHistograms() {
int input_fps =
static_cast<int>(input_frame_rate_tracker_total_.units_second());
- int sent_fps =
- static_cast<int>(sent_frame_rate_tracker_total_.units_second());
-
if (input_fps > 0)
RTC_HISTOGRAM_COUNTS_100("WebRTC.Video.InputFramesPerSecond", input_fps);
+ int sent_fps =
+ static_cast<int>(sent_frame_rate_tracker_total_.units_second());
if (sent_fps > 0)
RTC_HISTOGRAM_COUNTS_100("WebRTC.Video.SentFramesPerSecond", sent_fps);
+
+ const int kMinRequiredSamples = 100;
+ int in_width = input_width_counter_.Avg(kMinRequiredSamples);
+ int in_height = input_height_counter_.Avg(kMinRequiredSamples);
+ if (in_width != -1) {
+ RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.InputWidthInPixels", in_width);
+ RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.InputHeightInPixels", in_height);
+ }
+ int sent_width = sent_width_counter_.Avg(kMinRequiredSamples);
+ int sent_height = sent_height_counter_.Avg(kMinRequiredSamples);
+ if (sent_width != -1) {
+ RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.SentWidthInPixels", sent_width);
+ RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.SentHeightInPixels", sent_height);
+ }
}
void SendStatisticsProxy::OutgoingRate(const int video_channel,
@@ -139,16 +157,33 @@
stats->width = encoded_image._encodedWidth;
stats->height = encoded_image._encodedHeight;
update_times_[ssrc].resolution_update_ms = clock_->TimeInMilliseconds();
- if (encoded_image._timeStamp != last_sent_frame_timestamp_) {
- last_sent_frame_timestamp_ = encoded_image._timeStamp;
+
+ // TODO(asapersson): This is incorrect if simulcast layers are encoded on
+ // different threads and there is no guarantee that one frame of all layers
+ // are encoded before the next start.
+ if (last_sent_frame_timestamp_ > 0 &&
+ encoded_image._timeStamp != last_sent_frame_timestamp_) {
sent_frame_rate_tracker_total_.Update(1);
+ sent_width_counter_.Add(max_sent_width_per_timestamp_);
+ sent_height_counter_.Add(max_sent_height_per_timestamp_);
+ max_sent_width_per_timestamp_ = 0;
+ max_sent_height_per_timestamp_ = 0;
}
+ last_sent_frame_timestamp_ = encoded_image._timeStamp;
+ max_sent_width_per_timestamp_ =
+ std::max(max_sent_width_per_timestamp_,
+ static_cast<int>(encoded_image._encodedWidth));
+ max_sent_height_per_timestamp_ =
+ std::max(max_sent_height_per_timestamp_,
+ static_cast<int>(encoded_image._encodedHeight));
}
-void SendStatisticsProxy::OnIncomingFrame() {
+void SendStatisticsProxy::OnIncomingFrame(int width, int height) {
rtc::CritScope lock(&crit_);
input_frame_rate_tracker_.Update(1);
input_frame_rate_tracker_total_.Update(1);
+ input_width_counter_.Add(width);
+ input_height_counter_.Add(height);
}
void SendStatisticsProxy::RtcpPacketTypesCounterUpdated(
@@ -219,4 +254,15 @@
stats->max_delay_ms = max_delay_ms;
}
+void SendStatisticsProxy::SampleCounter::Add(int sample) {
+ sum += sample;
+ ++num_samples;
+}
+
+int SendStatisticsProxy::SampleCounter::Avg(int min_required_samples) const {
+ if (num_samples < min_required_samples || num_samples == 0)
+ return -1;
+ return sum / num_samples;
+}
+
} // namespace webrtc
diff --git a/webrtc/video/send_statistics_proxy.h b/webrtc/video/send_statistics_proxy.h
index 956a8f6..1d37f18 100644
--- a/webrtc/video/send_statistics_proxy.h
+++ b/webrtc/video/send_statistics_proxy.h
@@ -47,7 +47,7 @@
virtual void OnSendEncodedImage(const EncodedImage& encoded_image,
const RTPVideoHeader* rtp_video_header);
// Used to update incoming frame rate.
- void OnIncomingFrame();
+ void OnIncomingFrame(int width, int height);
// From VideoEncoderRateObserver.
void OnSetRates(uint32_t bitrate_bps, int framerate) override;
@@ -61,7 +61,7 @@
void StatisticsUpdated(const RtcpStatistics& statistics,
uint32_t ssrc) override;
void CNameChanged(const char* cname, uint32_t ssrc) override;
- // From RtcpPacketTypeCounterObserver
+ // From RtcpPacketTypeCounterObserver.
void RtcpPacketTypesCounterUpdated(
uint32_t ssrc,
const RtcpPacketTypeCounter& packet_counter) override;
@@ -90,6 +90,15 @@
uint32_t ssrc) override;
private:
+ struct SampleCounter {
+ SampleCounter() : sum(0), num_samples(0) {}
+ void Add(int sample);
+ int Avg(int min_required_samples) const;
+
+ private:
+ int sum;
+ int num_samples;
+ };
struct StatsUpdateTimes {
StatsUpdateTimes() : resolution_update_ms(0) {}
int64_t resolution_update_ms;
@@ -109,6 +118,13 @@
rtc::RateTracker sent_frame_rate_tracker_total_ GUARDED_BY(crit_);
uint32_t last_sent_frame_timestamp_ GUARDED_BY(crit_);
std::map<uint32_t, StatsUpdateTimes> update_times_ GUARDED_BY(crit_);
+
+ int max_sent_width_per_timestamp_ GUARDED_BY(crit_);
+ int max_sent_height_per_timestamp_ GUARDED_BY(crit_);
+ SampleCounter input_width_counter_ GUARDED_BY(crit_);
+ SampleCounter input_height_counter_ GUARDED_BY(crit_);
+ SampleCounter sent_width_counter_ GUARDED_BY(crit_);
+ SampleCounter sent_height_counter_ GUARDED_BY(crit_);
};
} // namespace webrtc
diff --git a/webrtc/video/video_capture_input.cc b/webrtc/video/video_capture_input.cc
index ecd7a30..8aae44f 100644
--- a/webrtc/video/video_capture_input.cc
+++ b/webrtc/video/video_capture_input.cc
@@ -78,7 +78,7 @@
if (local_renderer_)
local_renderer_->RenderFrame(video_frame, 0);
- stats_proxy_->OnIncomingFrame();
+ stats_proxy_->OnIncomingFrame(video_frame.width(), video_frame.height());
VideoFrame incoming_frame = video_frame;
diff --git a/webrtc/video/video_receive_stream.cc b/webrtc/video/video_receive_stream.cc
index 6d6619a..d770f58 100644
--- a/webrtc/video/video_receive_stream.cc
+++ b/webrtc/video/video_receive_stream.cc
@@ -318,7 +318,7 @@
video_frame,
video_frame.render_time_ms() - clock_->TimeInMilliseconds());
- stats_proxy_->OnRenderedFrame();
+ stats_proxy_->OnRenderedFrame(video_frame.width(), video_frame.height());
return 0;
}