Add histogram for percentage of sent frames that are limited in resolution due to bandwidth:
- "WebRTC.Video.BandwidthLimitedResolutionInPercent"
If the frame is bandwidth limited, the average number of disabled resolutions is logged:
- "WebRTC.Video.BandwidthLimitedResolutionsDisabled"
BUG=
Review URL: https://codereview.webrtc.org/1311533012
Cr-Commit-Position: refs/heads/master@{#10333}
diff --git a/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc b/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc
index d6f36f2..6ac840e 100644
--- a/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc
+++ b/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc
@@ -131,6 +131,15 @@
}
return true;
}
+
+int NumStreamsDisabled(std::vector<bool>& streams) {
+ int num_disabled = 0;
+ for (bool stream : streams) {
+ if (!stream)
+ ++num_disabled;
+ }
+ return num_disabled;
+}
} // namespace
const float kTl1MaxTimeToDropFrames = 20.0f;
@@ -951,6 +960,9 @@
int VP8EncoderImpl::GetEncodedPartitions(const VideoFrame& input_image,
bool only_predicting_from_key_frame) {
+ int bw_resolutions_disabled =
+ (encoders_.size() > 1) ? NumStreamsDisabled(send_stream_) : -1;
+
int stream_idx = static_cast<int>(encoders_.size()) - 1;
int result = WEBRTC_VIDEO_CODEC_OK;
for (size_t encoder_idx = 0; encoder_idx < encoders_.size();
@@ -1018,6 +1030,9 @@
encoded_images_[encoder_idx]
.adapt_reason_.quality_resolution_downscales =
quality_scaler_enabled_ ? quality_scaler_.downscale_shift() : -1;
+ // Report once per frame (lowest stream always sent).
+ encoded_images_[encoder_idx].adapt_reason_.bw_resolutions_disabled =
+ (stream_idx == 0) ? bw_resolutions_disabled : -1;
encoded_complete_callback_->Encoded(encoded_images_[encoder_idx],
&codec_specific, &frag_info);
} else if (codec_.mode == kScreensharing) {
diff --git a/webrtc/video/send_statistics_proxy.cc b/webrtc/video/send_statistics_proxy.cc
index 00edd06..32b7902 100644
--- a/webrtc/video/send_statistics_proxy.cc
+++ b/webrtc/video/send_statistics_proxy.cc
@@ -81,6 +81,16 @@
RTC_HISTOGRAM_ENUMERATION("WebRTC.Video.QualityLimitedResolutionDownscales",
downscales, 20);
}
+ int bw_limited = bw_limited_frame_counter_.Percent(kMinRequiredSamples);
+ if (bw_limited != -1) {
+ RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.BandwidthLimitedResolutionInPercent",
+ bw_limited);
+ }
+ int num_disabled = bw_resolutions_disabled_counter_.Avg(kMinRequiredSamples);
+ if (num_disabled != -1) {
+ RTC_HISTOGRAM_ENUMERATION(
+ "WebRTC.Video.BandwidthLimitedResolutionsDisabled", num_disabled, 10);
+ }
}
void SendStatisticsProxy::OnOutgoingRate(uint32_t framerate, uint32_t bitrate) {
@@ -190,6 +200,14 @@
encoded_image.adapt_reason_.quality_resolution_downscales);
}
}
+ if (encoded_image.adapt_reason_.bw_resolutions_disabled != -1) {
+ bool bw_limited = encoded_image.adapt_reason_.bw_resolutions_disabled > 0;
+ bw_limited_frame_counter_.Add(bw_limited);
+ if (bw_limited) {
+ bw_resolutions_disabled_counter_.Add(
+ encoded_image.adapt_reason_.bw_resolutions_disabled);
+ }
+ }
// TODO(asapersson): This is incorrect if simulcast layers are encoded on
// different threads and there is no guarantee that one frame of all layers
@@ -299,7 +317,7 @@
int SendStatisticsProxy::SampleCounter::Avg(int min_required_samples) const {
if (num_samples < min_required_samples || num_samples == 0)
return -1;
- return sum / num_samples;
+ return (sum + (num_samples / 2)) / num_samples;
}
void SendStatisticsProxy::BoolSampleCounter::Add(bool sample) {
diff --git a/webrtc/video/send_statistics_proxy.h b/webrtc/video/send_statistics_proxy.h
index cd2327e..7451bb5 100644
--- a/webrtc/video/send_statistics_proxy.h
+++ b/webrtc/video/send_statistics_proxy.h
@@ -87,8 +87,10 @@
uint32_t ssrc) override;
private:
- struct SampleCounter {
+ class SampleCounter {
+ public:
SampleCounter() : sum(0), num_samples(0) {}
+ ~SampleCounter() {}
void Add(int sample);
int Avg(int min_required_samples) const;
@@ -96,8 +98,10 @@
int sum;
int num_samples;
};
- struct BoolSampleCounter {
+ class BoolSampleCounter {
+ public:
BoolSampleCounter() : sum(0), num_samples(0) {}
+ ~BoolSampleCounter() {}
void Add(bool sample);
int Percent(int min_required_samples) const;
int Permille(int min_required_samples) const;
@@ -136,6 +140,8 @@
BoolSampleCounter key_frame_counter_ GUARDED_BY(crit_);
BoolSampleCounter quality_limited_frame_counter_ GUARDED_BY(crit_);
SampleCounter quality_downscales_counter_ GUARDED_BY(crit_);
+ BoolSampleCounter bw_limited_frame_counter_ GUARDED_BY(crit_);
+ SampleCounter bw_resolutions_disabled_counter_ GUARDED_BY(crit_);
};
} // namespace webrtc
diff --git a/webrtc/video_frame.h b/webrtc/video_frame.h
index 1968a69..821bfc2 100644
--- a/webrtc/video_frame.h
+++ b/webrtc/video_frame.h
@@ -167,6 +167,7 @@
VideoRotation rotation_;
};
+
// TODO(pbos): Rename EncodedFrame and reformat this class' members.
class EncodedImage {
public:
@@ -176,11 +177,15 @@
struct AdaptReason {
AdaptReason()
- : quality_resolution_downscales(-1) {}
+ : quality_resolution_downscales(-1),
+ bw_resolutions_disabled(-1) {}
int quality_resolution_downscales; // Number of times this frame is down
// scaled in resolution due to quality.
// Or -1 if information is not provided.
+ int bw_resolutions_disabled; // Number of resolutions that are not sent
+ // due to bandwidth for this frame.
+ // Or -1 if information is not provided.
};
uint32_t _encodedWidth = 0;
uint32_t _encodedHeight = 0;