Add stats googHasEnteredLowResolution.

Indicates if the forced sw fallback has had an effect (or would have had an effect if it had been
enabled).


Bug: webrtc:6634
Change-Id: I574b9001a2fae650fb894a1caa0d0f84257658e3
Reviewed-on: https://webrtc-review.googlesource.com/23300
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Commit-Queue: Åsa Persson <asapersson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20729}
This commit is contained in:
Åsa Persson 2017-11-16 14:04:52 +01:00 committed by Commit Bot
parent 12ab00b4d8
commit c3ed630560
10 changed files with 135 additions and 19 deletions

View File

@ -547,6 +547,8 @@ const char* StatsReport::Value::display_name() const {
return "googFrameWidthReceived";
case kStatsValueNameFrameWidthSent:
return "googFrameWidthSent";
case kStatsValueNameHasEnteredLowResolution:
return "googHasEnteredLowResolution";
case kStatsValueNameInitiator:
return "googInitiator";
case kStatsValueNameInterframeDelayMaxMs:

View File

@ -185,6 +185,7 @@ class StatsReport {
kStatsValueNameFrameWidthInput,
kStatsValueNameFrameWidthReceived,
kStatsValueNameFrameWidthSent,
kStatsValueNameHasEnteredLowResolution,
kStatsValueNameInitiator,
kStatsValueNameInterframeDelayMaxMs, // Max over last 10 seconds.
kStatsValueNameIssuerId,

View File

@ -85,6 +85,7 @@ class VideoSendStream {
// CPU/quality adaptation.
int number_of_cpu_adapt_changes = 0;
int number_of_quality_adapt_changes = 0;
bool has_entered_low_resolution = false;
std::map<uint32_t, StreamStats> substreams;
webrtc::VideoContentType content_type =
webrtc::VideoContentType::UNSPECIFIED;

View File

@ -723,6 +723,7 @@ struct VideoSenderInfo : public MediaSenderInfo {
avg_encode_ms(0),
encode_usage_percent(0),
frames_encoded(0),
has_entered_low_resolution(false),
content_type(webrtc::VideoContentType::UNSPECIFIED) {}
std::vector<SsrcGroup> ssrc_groups;
@ -743,6 +744,7 @@ struct VideoSenderInfo : public MediaSenderInfo {
int avg_encode_ms;
int encode_usage_percent;
uint32_t frames_encoded;
bool has_entered_low_resolution;
rtc::Optional<uint64_t> qp_sum;
webrtc::VideoContentType content_type;
};

View File

@ -1975,6 +1975,7 @@ VideoSenderInfo WebRtcVideoChannel::WebRtcVideoSendStream::GetVideoSenderInfo(
info.adapt_changes = stats.number_of_cpu_adapt_changes;
info.adapt_reason =
stats.cpu_limited_resolution ? ADAPTREASON_CPU : ADAPTREASON_NONE;
info.has_entered_low_resolution = stats.has_entered_low_resolution;
// Get bandwidth limitation info from stream_->GetStats().
// Input resolution (output from video_adapter) can be further scaled down or

View File

@ -317,6 +317,9 @@ void ExtractStats(const cricket::VideoSenderInfo& info, StatsReport* report) {
(info.adapt_reason & 0x2) > 0);
report->AddBoolean(StatsReport::kStatsValueNameCpuLimitedResolution,
(info.adapt_reason & 0x1) > 0);
report->AddBoolean(StatsReport::kStatsValueNameHasEnteredLowResolution,
info.has_entered_low_resolution);
if (info.qp_sum)
report->AddInt(StatsReport::kStatsValueNameQpSum, *info.qp_sum);

View File

@ -85,29 +85,37 @@ bool IsForcedFallbackPossible(const CodecSpecificInfo* codec_info) {
codec_info->codecSpecific.VP8.temporalIdx == kNoTemporalIdx);
}
rtc::Optional<int> GetFallbackMaxPixelsFromFieldTrial() {
if (!webrtc::field_trial::IsEnabled(kVp8ForcedFallbackEncoderFieldTrial))
return rtc::Optional<int>();
std::string group =
webrtc::field_trial::FindFullName(kVp8ForcedFallbackEncoderFieldTrial);
rtc::Optional<int> GetFallbackMaxPixels(const std::string& group) {
if (group.empty())
return rtc::Optional<int>();
int min_pixels;
int max_pixels;
int min_bps;
if (sscanf(group.c_str(), "Enabled-%d,%d,%d", &min_pixels, &max_pixels,
&min_bps) != 3) {
if (sscanf(group.c_str(), "-%d,%d,%d", &min_pixels, &max_pixels, &min_bps) !=
3) {
return rtc::Optional<int>();
}
if (min_pixels <= 0 || max_pixels <= 0 || max_pixels < min_pixels ||
min_bps <= 0) {
return rtc::Optional<int>(); // Do not log stats.
}
if (min_pixels <= 0 || max_pixels <= 0 || max_pixels < min_pixels)
return rtc::Optional<int>();
return rtc::Optional<int>(max_pixels);
}
rtc::Optional<int> GetFallbackMaxPixelsIfFieldTrialEnabled() {
std::string group =
webrtc::field_trial::FindFullName(kVp8ForcedFallbackEncoderFieldTrial);
return (group.find("Enabled") == 0) ? GetFallbackMaxPixels(group.substr(7))
: rtc::Optional<int>();
}
rtc::Optional<int> GetFallbackMaxPixelsIfFieldTrialDisabled() {
std::string group =
webrtc::field_trial::FindFullName(kVp8ForcedFallbackEncoderFieldTrial);
return (group.find("Disabled") == 0) ? GetFallbackMaxPixels(group.substr(8))
: rtc::Optional<int>();
}
} // namespace
@ -120,7 +128,8 @@ SendStatisticsProxy::SendStatisticsProxy(
: clock_(clock),
payload_name_(config.encoder_settings.payload_name),
rtp_config_(config.rtp),
fallback_max_pixels_(GetFallbackMaxPixelsFromFieldTrial()),
fallback_max_pixels_(GetFallbackMaxPixelsIfFieldTrialEnabled()),
fallback_max_pixels_disabled_(GetFallbackMaxPixelsIfFieldTrialDisabled()),
content_type_(content_type),
start_ms_(clock->TimeInMilliseconds()),
encode_time_(kEncodeTimeWeigthFactor),
@ -729,6 +738,8 @@ void SendStatisticsProxy::OnSetEncoderTargetRate(uint32_t bitrate_bps) {
void SendStatisticsProxy::UpdateEncoderFallbackStats(
const CodecSpecificInfo* codec_info,
int pixels) {
UpdateFallbackDisabledStats(codec_info, pixels);
if (!fallback_max_pixels_ || !uma_container_->fallback_info_.is_possible) {
return;
}
@ -755,6 +766,7 @@ void SendStatisticsProxy::UpdateEncoderFallbackStats(
fallback_info->is_possible = false;
return;
}
stats_.has_entered_low_resolution = true;
++fallback_info->on_off_events;
}
@ -772,6 +784,32 @@ void SendStatisticsProxy::UpdateEncoderFallbackStats(
fallback_info->last_update_ms.emplace(now_ms);
}
void SendStatisticsProxy::UpdateFallbackDisabledStats(
const CodecSpecificInfo* codec_info,
int pixels) {
if (!fallback_max_pixels_disabled_ ||
!uma_container_->fallback_info_disabled_.is_possible ||
stats_.has_entered_low_resolution) {
return;
}
if (!IsForcedFallbackPossible(codec_info) ||
strcmp(codec_info->codec_name, kVp8SwCodecName) == 0) {
uma_container_->fallback_info_disabled_.is_possible = false;
return;
}
if (pixels <= *fallback_max_pixels_disabled_ ||
uma_container_->fallback_info_disabled_.min_pixel_limit_reached) {
stats_.has_entered_low_resolution = true;
}
}
void SendStatisticsProxy::OnMinPixelLimitReached() {
rtc::CritScope lock(&crit_);
uma_container_->fallback_info_disabled_.min_pixel_limit_reached = true;
}
void SendStatisticsProxy::OnSendEncodedImage(
const EncodedImage& encoded_image,
const CodecSpecificInfo* codec_info) {

View File

@ -73,6 +73,7 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver,
void OnQualityAdaptationChanged(
const VideoStreamEncoder::AdaptCounts& cpu_counts,
const VideoStreamEncoder::AdaptCounts& quality_counts);
void OnMinPixelLimitReached();
void OnSuspendChange(bool is_suspended);
void OnInactiveSsrc(uint32_t ssrc);
@ -163,6 +164,10 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver,
rtc::Optional<int64_t> last_update_ms;
const int max_frame_diff_ms = 2000;
};
struct FallbackEncoderInfoDisabled {
bool is_possible = true;
bool min_pixel_limit_reached = false;
};
struct StatsTimer {
void Start(int64_t now_ms);
void Stop(int64_t now_ms);
@ -208,11 +213,15 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver,
void UpdateEncoderFallbackStats(const CodecSpecificInfo* codec_info,
int pixels)
RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
void UpdateFallbackDisabledStats(const CodecSpecificInfo* codec_info,
int pixels)
RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
Clock* const clock_;
const std::string payload_name_;
const VideoSendStream::Config::Rtp rtp_config_;
const rtc::Optional<int> fallback_max_pixels_;
const rtc::Optional<int> fallback_max_pixels_disabled_;
rtc::CriticalSection crit_;
VideoEncoderConfig::ContentType content_type_ RTC_GUARDED_BY(crit_);
const int64_t start_ms_;
@ -273,6 +282,7 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver,
TargetRateUpdates target_rate_updates_;
BoolSampleCounter fallback_active_counter_;
FallbackEncoderInfo fallback_info_;
FallbackEncoderInfoDisabled fallback_info_disabled_;
ReportBlockStats report_block_stats_;
const VideoSendStream::Stats start_stats_;
EncodedFrameMap encoded_frames_;

View File

@ -1867,7 +1867,8 @@ class ForcedFallbackTest : public SendStatisticsProxyTest {
class ForcedFallbackDisabled : public ForcedFallbackTest {
public:
ForcedFallbackDisabled()
: ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled/") {}
: ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
std::to_string(kWidth * kHeight) + ",3/") {}
};
class ForcedFallbackEnabled : public ForcedFallbackTest {
@ -1886,6 +1887,7 @@ TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
TEST_F(ForcedFallbackEnabled, StatsUpdated) {
InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
statistics_proxy_.reset();
EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
@ -1924,11 +1926,50 @@ TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
}
TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
InsertEncodedFrames(1, kFrameIntervalMs);
EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
}
TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
InsertEncodedFrames(1, kFrameIntervalMs);
EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
}
TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
codec_info_.codec_name = "libvpx";
InsertEncodedFrames(1, kFrameIntervalMs);
EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
}
TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
encoded_image_._encodedWidth = kWidth + 1;
InsertEncodedFrames(1, kFrameIntervalMs);
EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
}
TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
codec_info_.codec_name = "libvpx";
InsertEncodedFrames(1, kFrameIntervalMs);
EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
}
TEST_F(ForcedFallbackDisabled,
EnteredLowResolutionSetIfOnMinPixelLimitReached) {
encoded_image_._encodedWidth = kWidth + 1;
statistics_proxy_->OnMinPixelLimitReached();
InsertEncodedFrames(1, kFrameIntervalMs);
EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
}
TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
// One change. Video: 20000 ms, fallback: 5000 ms (25%).
EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
InsertEncodedFrames(15, 1000);
EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
codec_info_.codec_name = "libvpx";
InsertEncodedFrames(5, 1000);
EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
statistics_proxy_.reset();
EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
@ -1943,16 +1984,21 @@ TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
// Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
InsertEncodedFrames(10, 1000);
EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
codec_info_.codec_name = "libvpx";
InsertEncodedFrames(15, 500);
EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
codec_info_.codec_name = "notlibvpx";
InsertEncodedFrames(20, 1000);
InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
InsertEncodedFrames(10, 1000);
EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
codec_info_.codec_name = "notlibvpx2";
InsertEncodedFrames(10, 500);
EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
codec_info_.codec_name = "libvpx";
InsertEncodedFrames(15, 500);
EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
statistics_proxy_.reset();
EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
@ -1966,6 +2012,7 @@ TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
codec_info_.codec_name = "libvpx";
InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
statistics_proxy_.reset();
EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
@ -1976,6 +2023,7 @@ TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
codec_info_.codec_name = "libvpx";
InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
statistics_proxy_.reset();
EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));

View File

@ -228,7 +228,9 @@ class VideoStreamEncoder::VideoSourceProxy {
source_->AddOrUpdateSink(video_stream_encoder_, sink_wants_);
}
bool RequestResolutionLowerThan(int pixel_count, int min_pixels_per_frame) {
bool RequestResolutionLowerThan(int pixel_count,
int min_pixels_per_frame,
bool* min_pixels_reached) {
// Called on the encoder task queue.
rtc::CritScope lock(&crit_);
if (!source_ || !IsResolutionScalingEnabled(degradation_preference_)) {
@ -239,8 +241,11 @@ class VideoStreamEncoder::VideoSourceProxy {
// The input video frame size will have a resolution less than or equal to
// |max_pixel_count| depending on how the source can scale the frame size.
const int pixels_wanted = (pixel_count * 3) / 5;
if (pixels_wanted < min_pixels_per_frame ||
pixels_wanted >= sink_wants_.max_pixel_count) {
if (pixels_wanted >= sink_wants_.max_pixel_count) {
return false;
}
if (pixels_wanted < min_pixels_per_frame) {
*min_pixels_reached = true;
return false;
}
RTC_LOG(LS_INFO) << "Scaling down resolution, max pixels: "
@ -977,15 +982,20 @@ void VideoStreamEncoder::AdaptDown(AdaptReason reason) {
// Scale down resolution.
FALLTHROUGH();
}
case VideoSendStream::DegradationPreference::kMaintainFramerate:
case VideoSendStream::DegradationPreference::kMaintainFramerate: {
// Scale down resolution.
bool min_pixels_reached = false;
if (!source_proxy_->RequestResolutionLowerThan(
adaptation_request.input_pixel_count_,
settings_.encoder->GetScalingSettings().min_pixels_per_frame)) {
settings_.encoder->GetScalingSettings().min_pixels_per_frame,
&min_pixels_reached)) {
if (min_pixels_reached)
stats_proxy_->OnMinPixelLimitReached();
return;
}
GetAdaptCounter().IncrementResolution(reason);
break;
}
case VideoSendStream::DegradationPreference::kMaintainResolution: {
// Scale down framerate.
const int requested_framerate = source_proxy_->RequestFramerateLowerThan(