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}
This commit is contained in:
asapersson 2015-07-22 06:52:00 -07:00 committed by Commit bot
parent 65eb1c3df9
commit d89920b74a
8 changed files with 145 additions and 22 deletions

View File

@ -97,6 +97,8 @@ int32_t FakeEncoder::Encode(const VideoFrame& input_image,
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;

View File

@ -1634,10 +1634,32 @@ void EndToEndTest::VerifyHistogramStats(bool use_rtx, bool use_red) {
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"));

View File

@ -28,16 +28,24 @@ ReceiveStatisticsProxy::~ReceiveStatisticsProxy() {
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 @@ void ReceiveStatisticsProxy::OnDecodedFrame() {
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 @@ void ReceiveStatisticsProxy::OnDiscardedPacketsUpdated(int discarded_packets) {
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

View File

@ -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 @@ class ReceiveStatisticsProxy : public ViEDecoderObserver,
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 @@ class ReceiveStatisticsProxy : public ViEDecoderObserver,
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 @@ class ReceiveStatisticsProxy : public ViEDecoderObserver,
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_);
};

View File

@ -10,6 +10,7 @@
#include "webrtc/video/send_statistics_proxy.h"
#include <algorithm>
#include <map>
#include "webrtc/base/checks.h"
@ -24,7 +25,11 @@ const int SendStatisticsProxy::kStatsTimeoutMs = 5000;
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 @@ SendStatisticsProxy::~SendStatisticsProxy() {
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 @@ void SendStatisticsProxy::OnSendEncodedImage(
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 @@ void SendStatisticsProxy::SendSideDelayUpdated(int avg_delay_ms,
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

View File

@ -47,7 +47,7 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver,
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 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver,
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 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver,
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 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver,
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

View File

@ -78,7 +78,7 @@ void VideoCaptureInput::IncomingCapturedFrame(const VideoFrame& video_frame) {
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;

View File

@ -318,7 +318,7 @@ int VideoReceiveStream::RenderFrame(const uint32_t /*stream_id*/,
video_frame,
video_frame.render_time_ms() - clock_->TimeInMilliseconds());
stats_proxy_->OnRenderedFrame();
stats_proxy_->OnRenderedFrame(video_frame.width(), video_frame.height());
return 0;
}