Add power efficient stats to RTC stats
As the exposure of power efficient stats to JavaScript are limited as to reduce the fingerprinting surface to getStats, a new RTCStatsMember derivation, RTCLimitedStatsMember, was added in this change. This sets the exposure criteria of the stat on the type, which keeps the size of the RTCStatsMember class the same and allows for extension in the future for new types of stat restrictions. Bug: webrtc:14483 Change-Id: Ib0303050a112441ba2416fd5f004dd8be26b47ca Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/279021 Commit-Queue: Evan Shrubsole <eshr@webrtc.org> Reviewed-by: Henrik Boström <hbos@webrtc.org> Cr-Commit-Position: refs/heads/main@{#38576}
This commit is contained in:
parent
b456788d44
commit
13c0be44b3
@ -496,6 +496,8 @@ class RTC_EXPORT RTCInboundRTPStreamStats final
|
||||
// TimingFrameInfo::ToString().
|
||||
// TODO(https://crbug.com/webrtc/14586): Unship or standardize this metric.
|
||||
RTCStatsMember<std::string> goog_timing_frame_info;
|
||||
RTCRestrictedStatsMember<bool, StatExposureCriteria::kHardwareCapability>
|
||||
power_efficient_decoder;
|
||||
// Non-standard audio metrics.
|
||||
RTCNonStandardStatsMember<uint64_t> jitter_buffer_flushes;
|
||||
RTCNonStandardStatsMember<uint64_t> delayed_packet_outage_samples;
|
||||
@ -553,6 +555,8 @@ class RTC_EXPORT RTCOutboundRTPStreamStats final : public RTCRTPStreamStats {
|
||||
RTCStatsMember<uint32_t> nack_count;
|
||||
RTCStatsMember<uint64_t> qp_sum;
|
||||
RTCStatsMember<bool> active;
|
||||
RTCRestrictedStatsMember<bool, StatExposureCriteria::kHardwareCapability>
|
||||
power_efficient_encoder;
|
||||
};
|
||||
|
||||
// https://w3c.github.io/webrtc-stats/#remoteinboundrtpstats-dict*
|
||||
|
||||
@ -654,6 +654,10 @@ void SetInboundRTPStreamStatsFromVideoReceiverInfo(
|
||||
inbound_video->decoder_implementation =
|
||||
video_receiver_info.decoder_implementation_name;
|
||||
}
|
||||
if (video_receiver_info.power_efficient_decoder.has_value()) {
|
||||
inbound_video->power_efficient_decoder =
|
||||
video_receiver_info.power_efficient_decoder.value();
|
||||
}
|
||||
}
|
||||
|
||||
// Provides the media independent counters and information (both audio and
|
||||
@ -784,6 +788,10 @@ void SetOutboundRTPStreamStatsFromVideoSenderInfo(
|
||||
if (video_sender_info.rid.has_value()) {
|
||||
outbound_video->rid = *video_sender_info.rid;
|
||||
}
|
||||
if (video_sender_info.power_efficient_encoder.has_value()) {
|
||||
outbound_video->power_efficient_encoder =
|
||||
video_sender_info.power_efficient_encoder.value();
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<RTCRemoteInboundRtpStreamStats>
|
||||
|
||||
@ -2597,6 +2597,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) {
|
||||
absl::nullopt;
|
||||
video_media_info.receivers[0].decoder_implementation_name = "";
|
||||
video_media_info.receivers[0].min_playout_delay_ms = 50;
|
||||
video_media_info.receivers[0].power_efficient_decoder = false;
|
||||
|
||||
// Note: these two values intentionally differ,
|
||||
// only the decoded one should show up.
|
||||
@ -2661,6 +2662,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) {
|
||||
// `expected_video.decoder_implementation` should be undefined.
|
||||
expected_video.min_playout_delay = 0.05;
|
||||
expected_video.frames_per_second = 5;
|
||||
expected_video.power_efficient_decoder = false;
|
||||
|
||||
ASSERT_TRUE(report->Get(expected_video.id()));
|
||||
EXPECT_EQ(
|
||||
@ -2678,6 +2680,8 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) {
|
||||
expected_video.estimated_playout_timestamp = 1234;
|
||||
video_media_info.receivers[0].decoder_implementation_name = "libfoodecoder";
|
||||
expected_video.decoder_implementation = "libfoodecoder";
|
||||
video_media_info.receivers[0].power_efficient_decoder = true;
|
||||
expected_video.power_efficient_decoder = true;
|
||||
video_media_channel->SetStats(video_media_info);
|
||||
|
||||
report = stats_->GetFreshStatsReport();
|
||||
@ -2824,6 +2828,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) {
|
||||
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 = "";
|
||||
video_media_info.senders[0].power_efficient_encoder = false;
|
||||
video_media_info.senders[0].send_frame_width = 200;
|
||||
video_media_info.senders[0].send_frame_height = 100;
|
||||
video_media_info.senders[0].framerate_sent = 10;
|
||||
@ -2888,6 +2893,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) {
|
||||
expected_video.frames_sent = 5;
|
||||
expected_video.huge_frames_sent = 2;
|
||||
expected_video.active = false;
|
||||
expected_video.power_efficient_encoder = false;
|
||||
// `expected_video.content_type` should be undefined.
|
||||
// `expected_video.qp_sum` should be undefined.
|
||||
// `expected_video.encoder_implementation` should be undefined.
|
||||
@ -2905,6 +2911,8 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) {
|
||||
video_media_info.senders[0].encoder_implementation_name = "libfooencoder";
|
||||
video_media_info.aggregated_senders[0] = video_media_info.senders[0];
|
||||
expected_video.encoder_implementation = "libfooencoder";
|
||||
video_media_info.senders[0].power_efficient_encoder = true;
|
||||
expected_video.power_efficient_encoder = true;
|
||||
video_media_channel->SetStats(video_media_info);
|
||||
|
||||
report = stats_->GetFreshStatsReport();
|
||||
|
||||
@ -750,9 +750,15 @@ class RTCStatsReportVerifier {
|
||||
if (inbound_stream.kind.is_defined() && *inbound_stream.kind == "video") {
|
||||
verifier.TestMemberIsNonNegative<uint64_t>(inbound_stream.qp_sum);
|
||||
verifier.TestMemberIsDefined(inbound_stream.decoder_implementation);
|
||||
verifier.TestMemberIsDefined(inbound_stream.power_efficient_decoder);
|
||||
EXPECT_EQ(inbound_stream.power_efficient_decoder.exposure_criteria(),
|
||||
StatExposureCriteria::kHardwareCapability);
|
||||
} else {
|
||||
verifier.TestMemberIsUndefined(inbound_stream.qp_sum);
|
||||
verifier.TestMemberIsUndefined(inbound_stream.decoder_implementation);
|
||||
verifier.TestMemberIsUndefined(inbound_stream.power_efficient_decoder);
|
||||
EXPECT_EQ(inbound_stream.power_efficient_decoder.exposure_criteria(),
|
||||
StatExposureCriteria::kHardwareCapability);
|
||||
}
|
||||
verifier.TestMemberIsNonNegative<uint32_t>(inbound_stream.packets_received);
|
||||
if (inbound_stream.kind.is_defined() && *inbound_stream.kind == "audio") {
|
||||
@ -958,6 +964,9 @@ class RTCStatsReportVerifier {
|
||||
// this to be present.
|
||||
verifier.MarkMemberTested(outbound_stream.content_type, true);
|
||||
verifier.TestMemberIsDefined(outbound_stream.encoder_implementation);
|
||||
verifier.TestMemberIsDefined(outbound_stream.power_efficient_encoder);
|
||||
EXPECT_EQ(outbound_stream.power_efficient_encoder.exposure_criteria(),
|
||||
StatExposureCriteria::kHardwareCapability);
|
||||
// Unless an implementation-specific amount of time has passed and at
|
||||
// least one frame has been encoded, undefined is reported. Because it
|
||||
// is hard to tell what is the case here, we treat FPS as optional.
|
||||
@ -989,6 +998,7 @@ class RTCStatsReportVerifier {
|
||||
verifier.TestMemberIsUndefined(outbound_stream.content_type);
|
||||
// TODO(hbos): Implement for audio as well.
|
||||
verifier.TestMemberIsUndefined(outbound_stream.encoder_implementation);
|
||||
verifier.TestMemberIsUndefined(outbound_stream.power_efficient_encoder);
|
||||
verifier.TestMemberIsUndefined(outbound_stream.rid);
|
||||
verifier.TestMemberIsUndefined(outbound_stream.frames_per_second);
|
||||
verifier.TestMemberIsUndefined(outbound_stream.frame_height);
|
||||
|
||||
@ -561,6 +561,7 @@ WEBRTC_RTCSTATS_IMPL(
|
||||
&nack_count,
|
||||
&qp_sum,
|
||||
&goog_timing_frame_info,
|
||||
&power_efficient_decoder,
|
||||
&jitter_buffer_flushes,
|
||||
&delayed_packet_outage_samples,
|
||||
&relative_packet_arrival_delay,
|
||||
@ -625,6 +626,7 @@ RTCInboundRTPStreamStats::RTCInboundRTPStreamStats(std::string&& id,
|
||||
nack_count("nackCount"),
|
||||
qp_sum("qpSum"),
|
||||
goog_timing_frame_info("googTimingFrameInfo"),
|
||||
power_efficient_decoder("powerEfficientDecoder"),
|
||||
jitter_buffer_flushes(
|
||||
"jitterBufferFlushes",
|
||||
{NonStandardGroupId::kRtcAudioJitterBufferMaxPackets}),
|
||||
@ -675,7 +677,8 @@ WEBRTC_RTCSTATS_IMPL(
|
||||
&pli_count,
|
||||
&nack_count,
|
||||
&qp_sum,
|
||||
&active)
|
||||
&active,
|
||||
&power_efficient_encoder)
|
||||
// clang-format on
|
||||
|
||||
RTCOutboundRTPStreamStats::RTCOutboundRTPStreamStats(const std::string& id,
|
||||
@ -715,7 +718,8 @@ RTCOutboundRTPStreamStats::RTCOutboundRTPStreamStats(std::string&& id,
|
||||
pli_count("pliCount"),
|
||||
nack_count("nackCount"),
|
||||
qp_sum("qpSum"),
|
||||
active("active") {}
|
||||
active("active"),
|
||||
power_efficient_encoder("powerEfficientEncoder") {}
|
||||
|
||||
RTCOutboundRTPStreamStats::RTCOutboundRTPStreamStats(
|
||||
const RTCOutboundRTPStreamStats& other) = default;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user