Add qualityLimitationResolutionChanges stat
Implements the stat qualityLimitationResolutionChanges [1]. [1] https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-qualitylimitationresolutionchanges Bug: webrtc:10935 Change-Id: I391f2be5958a96b442e32c40ab7043752f3f71dd Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/150882 Reviewed-by: Erik Språng <sprang@webrtc.org> Reviewed-by: Henrik Boström <hbos@webrtc.org> Reviewed-by: Stefan Holmer <stefan@webrtc.org> Commit-Queue: Evan Shrubsole <eshr@google.com> Cr-Commit-Position: refs/heads/master@{#29113}
This commit is contained in:
parent
a8336d3cf4
commit
cc62b16658
@ -481,6 +481,8 @@ class RTC_EXPORT RTCOutboundRTPStreamStats final : public RTCRTPStreamStats {
|
||||
// qualityLimitationDurations. Requires RTCStatsMember support for
|
||||
// "record<DOMString, double>", see https://crbug.com/webrtc/10685.
|
||||
RTCStatsMember<std::string> quality_limitation_reason;
|
||||
// https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-qualitylimitationresolutionchanges
|
||||
RTCStatsMember<uint32_t> quality_limitation_resolution_changes;
|
||||
// https://henbos.github.io/webrtc-provisional-stats/#dom-rtcoutboundrtpstreamstats-contenttype
|
||||
RTCStatsMember<std::string> content_type;
|
||||
// TODO(hbos): This is only implemented for video; implement it for audio as
|
||||
|
||||
@ -223,8 +223,10 @@ rtc_source_set("video_stream_encoder") {
|
||||
]
|
||||
|
||||
deps = [
|
||||
":video_bitrate_allocation",
|
||||
":video_bitrate_allocator",
|
||||
":video_bitrate_allocator_factory",
|
||||
":video_codec_constants",
|
||||
":video_frame",
|
||||
"..:rtp_parameters",
|
||||
"../:fec_controller_api",
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/video/video_bitrate_allocation.h"
|
||||
#include "api/video/video_codec_constants.h"
|
||||
#include "api/video_codecs/video_encoder.h"
|
||||
#include "api/video_codecs/video_encoder_config.h"
|
||||
|
||||
@ -88,6 +90,10 @@ class VideoStreamEncoderObserver : public CpuOveruseMetricsObserver {
|
||||
|
||||
virtual void OnSuspendChange(bool is_suspended) = 0;
|
||||
|
||||
virtual void OnBitrateAllocationUpdated(
|
||||
const VideoCodec& codec,
|
||||
const VideoBitrateAllocation& allocation) {}
|
||||
|
||||
// TODO(nisse): VideoStreamEncoder wants to query the stats, which makes this
|
||||
// not a pure observer. GetInputFrameRate is needed for the cpu adaptation, so
|
||||
// can be deleted if that responsibility is moved out to a VideoStreamAdaptor
|
||||
|
||||
@ -99,6 +99,8 @@ class VideoSendStream {
|
||||
QualityLimitationReason::kNone;
|
||||
// https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-qualitylimitationdurations
|
||||
std::map<QualityLimitationReason, int64_t> quality_limitation_durations_ms;
|
||||
// https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-qualitylimitationresolutionchanges
|
||||
uint32_t quality_limitation_resolution_changes = 0;
|
||||
// Total number of times resolution as been requested to be changed due to
|
||||
// CPU/quality adaptation.
|
||||
int number_of_cpu_adapt_changes = 0;
|
||||
|
||||
@ -562,6 +562,8 @@ struct VideoSenderInfo : public MediaSenderInfo {
|
||||
// https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-qualitylimitationdurations
|
||||
std::map<webrtc::QualityLimitationReason, int64_t>
|
||||
quality_limitation_durations_ms;
|
||||
// https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-qualitylimitationresolutionchanges
|
||||
uint32_t quality_limitation_resolution_changes = 0;
|
||||
int avg_encode_ms = 0;
|
||||
int encode_usage_percent = 0;
|
||||
uint32_t frames_encoded = 0;
|
||||
|
||||
@ -2343,6 +2343,8 @@ VideoSenderInfo WebRtcVideoChannel::WebRtcVideoSendStream::GetVideoSenderInfo(
|
||||
|
||||
info.quality_limitation_reason = stats.quality_limitation_reason;
|
||||
info.quality_limitation_durations_ms = stats.quality_limitation_durations_ms;
|
||||
info.quality_limitation_resolution_changes =
|
||||
stats.quality_limitation_resolution_changes;
|
||||
info.encoder_implementation_name = stats.encoder_implementation_name;
|
||||
info.ssrc_groups = ssrc_groups_;
|
||||
info.framerate_input = stats.input_frame_rate;
|
||||
|
||||
@ -398,6 +398,8 @@ void SetOutboundRTPStreamStatsFromVideoSenderInfo(
|
||||
outbound_video->quality_limitation_reason =
|
||||
QualityLimitationReasonToRTCQualityLimitationReason(
|
||||
video_sender_info.quality_limitation_reason);
|
||||
outbound_video->quality_limitation_resolution_changes =
|
||||
video_sender_info.quality_limitation_resolution_changes;
|
||||
// TODO(https://crbug.com/webrtc/10529): When info's |content_info| is
|
||||
// optional, support the "unspecified" value.
|
||||
if (video_sender_info.content_type == VideoContentType::SCREENSHARE)
|
||||
|
||||
@ -1966,6 +1966,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) {
|
||||
video_media_info.senders[0].total_packet_send_delay_ms = 10000;
|
||||
video_media_info.senders[0].quality_limitation_reason =
|
||||
QualityLimitationReason::kBandwidth;
|
||||
video_media_info.senders[0].quality_limitation_resolution_changes = 56u;
|
||||
video_media_info.senders[0].qp_sum = absl::nullopt;
|
||||
video_media_info.senders[0].content_type = VideoContentType::UNSPECIFIED;
|
||||
video_media_info.senders[0].encoder_implementation_name = "";
|
||||
@ -2014,6 +2015,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) {
|
||||
expected_video.total_encoded_bytes_target = 1234;
|
||||
expected_video.total_packet_send_delay = 10.0;
|
||||
expected_video.quality_limitation_reason = "bandwidth";
|
||||
expected_video.quality_limitation_resolution_changes = 56u;
|
||||
// |expected_video.content_type| should be undefined.
|
||||
// |expected_video.qp_sum| should be undefined.
|
||||
// |expected_video.encoder_implementation| should be undefined.
|
||||
|
||||
@ -869,6 +869,8 @@ class RTCStatsReportVerifier {
|
||||
verifier.TestMemberIsNonNegative<double>(
|
||||
outbound_stream.total_packet_send_delay);
|
||||
verifier.TestMemberIsDefined(outbound_stream.quality_limitation_reason);
|
||||
verifier.TestMemberIsNonNegative<uint32_t>(
|
||||
outbound_stream.quality_limitation_resolution_changes);
|
||||
// The integration test is not set up to test screen share; don't require
|
||||
// this to be present.
|
||||
verifier.MarkMemberTested(outbound_stream.content_type, true);
|
||||
@ -882,6 +884,8 @@ class RTCStatsReportVerifier {
|
||||
// TODO(https://crbug.com/webrtc/10635): Implement for audio as well.
|
||||
verifier.TestMemberIsUndefined(outbound_stream.total_packet_send_delay);
|
||||
verifier.TestMemberIsUndefined(outbound_stream.quality_limitation_reason);
|
||||
verifier.TestMemberIsUndefined(
|
||||
outbound_stream.quality_limitation_resolution_changes);
|
||||
verifier.TestMemberIsUndefined(outbound_stream.content_type);
|
||||
// TODO(hbos): Implement for audio as well.
|
||||
verifier.TestMemberIsUndefined(outbound_stream.encoder_implementation);
|
||||
|
||||
@ -694,6 +694,7 @@ WEBRTC_RTCSTATS_IMPL(
|
||||
&total_encoded_bytes_target,
|
||||
&total_packet_send_delay,
|
||||
&quality_limitation_reason,
|
||||
&quality_limitation_resolution_changes,
|
||||
&content_type,
|
||||
&encoder_implementation)
|
||||
// clang-format on
|
||||
@ -717,6 +718,8 @@ RTCOutboundRTPStreamStats::RTCOutboundRTPStreamStats(std::string&& id,
|
||||
total_encoded_bytes_target("totalEncodedBytesTarget"),
|
||||
total_packet_send_delay("totalPacketSendDelay"),
|
||||
quality_limitation_reason("qualityLimitationReason"),
|
||||
quality_limitation_resolution_changes(
|
||||
"qualityLimitationResolutionChanges"),
|
||||
content_type("contentType"),
|
||||
encoder_implementation("encoderImplementation") {}
|
||||
|
||||
@ -735,6 +738,8 @@ RTCOutboundRTPStreamStats::RTCOutboundRTPStreamStats(
|
||||
total_encoded_bytes_target(other.total_encoded_bytes_target),
|
||||
total_packet_send_delay(other.total_packet_send_delay),
|
||||
quality_limitation_reason(other.quality_limitation_reason),
|
||||
quality_limitation_resolution_changes(
|
||||
other.quality_limitation_resolution_changes),
|
||||
content_type(other.content_type),
|
||||
encoder_implementation(other.encoder_implementation) {}
|
||||
|
||||
|
||||
@ -63,6 +63,7 @@ rtc_static_library("video") {
|
||||
"../api/video:encoded_image",
|
||||
"../api/video:video_bitrate_allocation",
|
||||
"../api/video:video_bitrate_allocator",
|
||||
"../api/video:video_codec_constants",
|
||||
"../api/video:video_frame",
|
||||
"../api/video:video_frame_i420",
|
||||
"../api/video:video_rtp_headers",
|
||||
@ -192,6 +193,7 @@ rtc_source_set("video_stream_encoder_impl") {
|
||||
"../api/video:video_bitrate_allocation",
|
||||
"../api/video:video_bitrate_allocator",
|
||||
"../api/video:video_bitrate_allocator_factory",
|
||||
"../api/video:video_codec_constants",
|
||||
"../api/video:video_frame",
|
||||
"../api/video:video_frame_i420",
|
||||
"../api/video:video_rtp_headers",
|
||||
|
||||
@ -21,12 +21,15 @@ namespace webrtc {
|
||||
// A tracker of quality limitation reasons. The quality limitation reason is the
|
||||
// primary reason for limiting resolution and/or framerate (such as CPU or
|
||||
// bandwidth limitations). The tracker keeps track of the current reason and the
|
||||
// duration of time spent in each reason. See qualityLimitationReason[1] and
|
||||
// qualityLimitationDurations[2] in the webrtc-stats spec.
|
||||
// duration of time spent in each reason. See qualityLimitationReason[1],
|
||||
// qualityLimitationDurations[2], and qualityLimitationResolutionChanges[3] in
|
||||
// the webrtc-stats spec.
|
||||
// [1]
|
||||
// https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-qualitylimitationreason
|
||||
// [2]
|
||||
// https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-qualitylimitationdurations
|
||||
// [3]
|
||||
// https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-qualitylimitationresolutionchanges
|
||||
class QualityLimitationReasonTracker {
|
||||
public:
|
||||
// The caller is responsible for making sure |clock| outlives the tracker.
|
||||
|
||||
@ -11,11 +11,15 @@
|
||||
#include "video/send_statistics_proxy.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/algorithm/container.h"
|
||||
#include "api/video/video_codec_constants.h"
|
||||
#include "api/video/video_codec_type.h"
|
||||
#include "api/video_codecs/video_codec.h"
|
||||
#include "modules/video_coding/include/video_codec_interface.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
@ -140,6 +144,9 @@ SendStatisticsProxy::SendStatisticsProxy(
|
||||
quality_limitation_reason_tracker_(clock_),
|
||||
media_byte_rate_tracker_(kBucketSizeMs, kBucketCount),
|
||||
encoded_frame_rate_tracker_(kBucketSizeMs, kBucketCount),
|
||||
last_num_spatial_layers_(0),
|
||||
last_num_simulcast_streams_(0),
|
||||
last_spatial_layer_use_{},
|
||||
uma_container_(
|
||||
new UmaSamplesContainer(GetUmaPrefix(content_type_), stats_, clock)) {
|
||||
}
|
||||
@ -1104,6 +1111,43 @@ void SendStatisticsProxy::UpdateAdaptationStats(
|
||||
// when it is polled; it is updated in SendStatisticsProxy::GetStats().
|
||||
}
|
||||
|
||||
void SendStatisticsProxy::OnBitrateAllocationUpdated(
|
||||
const VideoCodec& codec,
|
||||
const VideoBitrateAllocation& allocation) {
|
||||
int num_spatial_layers = 0;
|
||||
for (int i = 0; i < kMaxSpatialLayers; i++) {
|
||||
if (codec.spatialLayers[i].active) {
|
||||
num_spatial_layers++;
|
||||
}
|
||||
}
|
||||
int num_simulcast_streams = 0;
|
||||
for (int i = 0; i < kMaxSimulcastStreams; i++) {
|
||||
if (codec.simulcastStream[i].active) {
|
||||
num_simulcast_streams++;
|
||||
}
|
||||
}
|
||||
|
||||
std::array<bool, kMaxSpatialLayers> spatial_layers;
|
||||
for (int i = 0; i < kMaxSpatialLayers; i++) {
|
||||
spatial_layers[i] = (allocation.GetSpatialLayerSum(i) > 0);
|
||||
}
|
||||
|
||||
rtc::CritScope lock(&crit_);
|
||||
|
||||
if (spatial_layers != last_spatial_layer_use_) {
|
||||
// If the number of spatial layers has changed, the resolution change is
|
||||
// not due to quality limitations, it is because the configuration
|
||||
// changed.
|
||||
if (last_num_spatial_layers_ == num_spatial_layers &&
|
||||
last_num_simulcast_streams_ == num_simulcast_streams) {
|
||||
++stats_.quality_limitation_resolution_changes;
|
||||
}
|
||||
last_spatial_layer_use_ = spatial_layers;
|
||||
}
|
||||
last_num_spatial_layers_ = num_spatial_layers;
|
||||
last_num_simulcast_streams_ = num_simulcast_streams;
|
||||
}
|
||||
|
||||
// TODO(asapersson): Include fps changes.
|
||||
void SendStatisticsProxy::OnInitialQualityResolutionAdaptDown() {
|
||||
rtc::CritScope lock(&crit_);
|
||||
|
||||
@ -11,12 +11,15 @@
|
||||
#ifndef VIDEO_SEND_STATISTICS_PROXY_H_
|
||||
#define VIDEO_SEND_STATISTICS_PROXY_H_
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "api/video/video_codec_constants.h"
|
||||
#include "api/video/video_stream_encoder_observer.h"
|
||||
#include "api/video_codecs/video_encoder_config.h"
|
||||
#include "call/video_send_stream.h"
|
||||
#include "modules/rtp_rtcp/include/report_block_data.h"
|
||||
#include "modules/video_coding/include/video_codec_interface.h"
|
||||
@ -70,6 +73,10 @@ class SendStatisticsProxy : public VideoStreamEncoderObserver,
|
||||
const AdaptationSteps& cpu_counts,
|
||||
const AdaptationSteps& quality_counts) override;
|
||||
|
||||
void OnBitrateAllocationUpdated(
|
||||
const VideoCodec& codec,
|
||||
const VideoBitrateAllocation& allocation) override;
|
||||
|
||||
void OnMinPixelLimitReached() override;
|
||||
void OnInitialQualityResolutionAdaptDown() override;
|
||||
|
||||
@ -251,6 +258,11 @@ class SendStatisticsProxy : public VideoStreamEncoderObserver,
|
||||
|
||||
absl::optional<int64_t> last_outlier_timestamp_ RTC_GUARDED_BY(crit_);
|
||||
|
||||
int last_num_spatial_layers_ RTC_GUARDED_BY(crit_);
|
||||
int last_num_simulcast_streams_ RTC_GUARDED_BY(crit_);
|
||||
std::array<bool, kMaxSpatialLayers> last_spatial_layer_use_
|
||||
RTC_GUARDED_BY(crit_);
|
||||
|
||||
struct EncoderChangeEvent {
|
||||
std::string previous_encoder_implementation;
|
||||
std::string new_encoder_implementation;
|
||||
|
||||
@ -18,6 +18,10 @@
|
||||
|
||||
#include "absl/algorithm/container.h"
|
||||
#include "api/units/timestamp.h"
|
||||
#include "api/video/video_bitrate_allocation.h"
|
||||
#include "api/video/video_codec_type.h"
|
||||
#include "api/video_codecs/video_codec.h"
|
||||
#include "api/video_codecs/video_encoder_config.h"
|
||||
#include "rtc_base/fake_clock.h"
|
||||
#include "system_wrappers/include/metrics.h"
|
||||
#include "test/field_trial.h"
|
||||
@ -1206,6 +1210,167 @@ TEST_F(SendStatisticsProxyTest, QualityLimitationDurationIncreasesWithTime) {
|
||||
quality_limitation_durations_ms[QualityLimitationReason::kOther]);
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest, QualityLimitationResolutionChangesDefaultZero) {
|
||||
EXPECT_EQ(
|
||||
0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest,
|
||||
QualityLimitationResolutionChangesNotChangesWithOnlyDefaultAllocation) {
|
||||
VideoCodec codec;
|
||||
VideoBitrateAllocation allocation;
|
||||
statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
|
||||
EXPECT_EQ(
|
||||
0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest,
|
||||
QualityLimitationResolutionChangesDoesNotIncreaseOnFirstAllocation) {
|
||||
VideoCodec codec;
|
||||
codec.simulcastStream[0].active = true;
|
||||
codec.simulcastStream[1].active = true;
|
||||
codec.simulcastStream[2].active = true;
|
||||
VideoBitrateAllocation allocation;
|
||||
allocation.SetBitrate(0, 0, 100);
|
||||
statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
|
||||
EXPECT_EQ(
|
||||
0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest,
|
||||
QualityLimitationResolutionChangesWhenNewLayerGetsBandwidth) {
|
||||
VideoCodec codec;
|
||||
codec.simulcastStream[0].active = true;
|
||||
codec.simulcastStream[1].active = true;
|
||||
codec.simulcastStream[2].active = true;
|
||||
VideoBitrateAllocation allocation;
|
||||
allocation.SetBitrate(0, 0, 100);
|
||||
statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
|
||||
allocation.SetBitrate(1, 0, 100);
|
||||
statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
|
||||
EXPECT_EQ(
|
||||
1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest,
|
||||
QualityLimitationResolutionDoesNotChangeWhenLayerSame) {
|
||||
VideoCodec codec;
|
||||
codec.simulcastStream[0].active = true;
|
||||
VideoBitrateAllocation allocation;
|
||||
allocation.SetBitrate(0, 0, 100);
|
||||
statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
|
||||
// Layer 0 got more bandwidth, but still only one layer on
|
||||
allocation.SetBitrate(0, 0, 200);
|
||||
statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
|
||||
EXPECT_EQ(
|
||||
0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest,
|
||||
QualityLimitationResolutionChangesWithTogglingLayers) {
|
||||
VideoCodec codec;
|
||||
codec.simulcastStream[0].active = true;
|
||||
codec.simulcastStream[1].active = true;
|
||||
codec.simulcastStream[2].active = true;
|
||||
VideoBitrateAllocation allocation;
|
||||
allocation.SetBitrate(0, 0, 100);
|
||||
statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
|
||||
EXPECT_EQ(
|
||||
0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
|
||||
allocation.SetBitrate(1, 0, 300);
|
||||
allocation.SetBitrate(2, 0, 500);
|
||||
statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
|
||||
EXPECT_EQ(
|
||||
1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
|
||||
// Layer 2 off
|
||||
allocation.SetBitrate(2, 0, 0);
|
||||
statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
|
||||
EXPECT_EQ(
|
||||
2u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
|
||||
// Layer 2 back on
|
||||
allocation.SetBitrate(2, 0, 500);
|
||||
statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
|
||||
EXPECT_EQ(
|
||||
3u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
|
||||
allocation.SetBitrate(0, 0, 0);
|
||||
allocation.SetBitrate(1, 0, 0);
|
||||
allocation.SetBitrate(2, 0, 0);
|
||||
// All layers off
|
||||
statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
|
||||
EXPECT_EQ(
|
||||
4u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest,
|
||||
QualityLimitationResolutionDoesNotUpdateOnCodecSimulcastStreamChanges) {
|
||||
VideoCodec codec;
|
||||
// 3 layers
|
||||
codec.simulcastStream[0].active = true;
|
||||
codec.simulcastStream[1].active = true;
|
||||
codec.simulcastStream[2].active = true;
|
||||
VideoBitrateAllocation allocation;
|
||||
allocation.SetBitrate(0, 0, 500);
|
||||
allocation.SetBitrate(1, 0, 500);
|
||||
allocation.SetBitrate(2, 0, 500);
|
||||
statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
|
||||
EXPECT_EQ(
|
||||
0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
|
||||
|
||||
// Down to one layer now, triggered by a config change
|
||||
codec.numberOfSimulcastStreams = 1;
|
||||
codec.simulcastStream[1].active = false;
|
||||
codec.simulcastStream[2].active = false;
|
||||
allocation.SetBitrate(0, 0, 100);
|
||||
statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
|
||||
EXPECT_EQ(
|
||||
0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
|
||||
|
||||
// Up to 3 layers again.
|
||||
codec.numberOfSimulcastStreams = 3;
|
||||
codec.simulcastStream[1].active = true;
|
||||
codec.simulcastStream[2].active = true;
|
||||
allocation.SetBitrate(0, 0, 500);
|
||||
allocation.SetBitrate(1, 0, 500);
|
||||
allocation.SetBitrate(2, 0, 500);
|
||||
statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
|
||||
EXPECT_EQ(
|
||||
0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest,
|
||||
QualityLimitationResolutionDoesNotUpdateForSpatialLayerChanges) {
|
||||
VideoCodec codec;
|
||||
codec.simulcastStream[0].active = true;
|
||||
codec.spatialLayers[0].active = true;
|
||||
codec.spatialLayers[1].active = true;
|
||||
codec.spatialLayers[2].active = true;
|
||||
VideoBitrateAllocation allocation;
|
||||
allocation.SetBitrate(0, 0, 500);
|
||||
allocation.SetBitrate(1, 0, 500);
|
||||
allocation.SetBitrate(2, 0, 500);
|
||||
statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
|
||||
EXPECT_EQ(
|
||||
0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
|
||||
|
||||
// Down to one layer now, triggered by a config change
|
||||
codec.spatialLayers[1].active = false;
|
||||
codec.spatialLayers[2].active = false;
|
||||
allocation.SetBitrate(0, 0, 100);
|
||||
statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
|
||||
EXPECT_EQ(
|
||||
0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
|
||||
|
||||
// Up to 3 layers again.
|
||||
codec.spatialLayers[1].active = true;
|
||||
codec.spatialLayers[2].active = true;
|
||||
allocation.SetBitrate(0, 0, 500);
|
||||
allocation.SetBitrate(1, 0, 500);
|
||||
allocation.SetBitrate(2, 0, 500);
|
||||
statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
|
||||
EXPECT_EQ(
|
||||
0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
|
||||
for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
|
||||
statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include "video/video_stream_encoder.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <utility>
|
||||
@ -20,6 +21,7 @@
|
||||
#include "api/video/encoded_image.h"
|
||||
#include "api/video/i420_buffer.h"
|
||||
#include "api/video/video_bitrate_allocator_factory.h"
|
||||
#include "api/video/video_codec_constants.h"
|
||||
#include "api/video_codecs/video_encoder.h"
|
||||
#include "modules/video_coding/codecs/vp9/svc_rate_allocator.h"
|
||||
#include "modules/video_coding/include/video_codec_initializer.h"
|
||||
@ -1169,6 +1171,9 @@ VideoStreamEncoder::UpdateBitrateAllocationAndNotifyObserver(
|
||||
new_rate_settings.bitrate = adjusted_allocation;
|
||||
}
|
||||
|
||||
encoder_stats_observer_->OnBitrateAllocationUpdated(
|
||||
send_codec_, new_rate_settings.bitrate);
|
||||
|
||||
return new_rate_settings;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user