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:
parent
12ab00b4d8
commit
c3ed630560
@ -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:
|
||||
|
||||
@ -185,6 +185,7 @@ class StatsReport {
|
||||
kStatsValueNameFrameWidthInput,
|
||||
kStatsValueNameFrameWidthReceived,
|
||||
kStatsValueNameFrameWidthSent,
|
||||
kStatsValueNameHasEnteredLowResolution,
|
||||
kStatsValueNameInitiator,
|
||||
kStatsValueNameInterframeDelayMaxMs, // Max over last 10 seconds.
|
||||
kStatsValueNameIssuerId,
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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_;
|
||||
|
||||
@ -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"));
|
||||
|
||||
@ -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(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user