diff --git a/api/stats/rtcstats_objects.h b/api/stats/rtcstats_objects.h index 8371543fad..208a3001da 100644 --- a/api/stats/rtcstats_objects.h +++ b/api/stats/rtcstats_objects.h @@ -279,6 +279,7 @@ class RTCMediaStreamTrackStats final : public RTCStats { // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137 RTCStatsMember frames_per_second; RTCStatsMember frames_sent; + RTCStatsMember huge_frames_sent; RTCStatsMember frames_received; RTCStatsMember frames_decoded; RTCStatsMember frames_dropped; diff --git a/api/statstypes.cc b/api/statstypes.cc index 8a8726530c..49a00bb37e 100644 --- a/api/statstypes.cc +++ b/api/statstypes.cc @@ -558,6 +558,8 @@ const char* StatsReport::Value::display_name() const { return "googFrameWidthSent"; case kStatsValueNameHasEnteredLowResolution: return "googHasEnteredLowResolution"; + case kStatsValueNameHugeFramesSent: + return "hugeFramesSent"; case kStatsValueNameInitiator: return "googInitiator"; case kStatsValueNameInterframeDelayMaxMs: diff --git a/api/statstypes.h b/api/statstypes.h index 9dc6154997..2e3de06904 100644 --- a/api/statstypes.h +++ b/api/statstypes.h @@ -189,6 +189,7 @@ class StatsReport { kStatsValueNameFrameWidthReceived, kStatsValueNameFrameWidthSent, kStatsValueNameHasEnteredLowResolution, + kStatsValueNameHugeFramesSent, kStatsValueNameInitiator, kStatsValueNameInterframeDelayMaxMs, // Max over last 10 seconds. kStatsValueNameIssuerId, diff --git a/call/video_send_stream.h b/call/video_send_stream.h index b5daa3e2a9..440b62e4a8 100644 --- a/call/video_send_stream.h +++ b/call/video_send_stream.h @@ -91,6 +91,7 @@ class VideoSendStream { std::map substreams; webrtc::VideoContentType content_type = webrtc::VideoContentType::UNSPECIFIED; + uint32_t huge_frames_sent = 0; }; struct Config { diff --git a/media/base/mediachannel.h b/media/base/mediachannel.h index a5831ff6e7..90fa40cff8 100644 --- a/media/base/mediachannel.h +++ b/media/base/mediachannel.h @@ -466,6 +466,8 @@ struct VideoSenderInfo : public MediaSenderInfo { bool has_entered_low_resolution = false; rtc::Optional qp_sum; webrtc::VideoContentType content_type = webrtc::VideoContentType::UNSPECIFIED; + // https://w3c.github.io/webrtc-stats/#dom-rtcvideosenderstats-hugeframessent + uint32_t huge_frames_sent = 0; }; struct VideoReceiverInfo : public MediaReceiverInfo { diff --git a/media/engine/webrtcvideoengine.cc b/media/engine/webrtcvideoengine.cc index de044d5d31..84916993b1 100644 --- a/media/engine/webrtcvideoengine.cc +++ b/media/engine/webrtcvideoengine.cc @@ -2058,6 +2058,7 @@ VideoSenderInfo WebRtcVideoChannel::WebRtcVideoSendStream::GetVideoSenderInfo( info.preferred_bitrate = stats.preferred_media_bitrate_bps; info.content_type = stats.content_type; + info.huge_frames_sent = stats.huge_frames_sent; info.send_frame_width = 0; info.send_frame_height = 0; diff --git a/pc/rtcstats_integrationtest.cc b/pc/rtcstats_integrationtest.cc index 158d54b41b..374c048b1f 100644 --- a/pc/rtcstats_integrationtest.cc +++ b/pc/rtcstats_integrationtest.cc @@ -515,6 +515,7 @@ class RTCStatsReportVerifier { verifier.TestMemberIsUndefined(media_stream_track.frames_per_second); if (*media_stream_track.remote_source) { verifier.TestMemberIsUndefined(media_stream_track.frames_sent); + verifier.TestMemberIsUndefined(media_stream_track.huge_frames_sent); verifier.TestMemberIsNonNegative( media_stream_track.frames_received); verifier.TestMemberIsNonNegative( @@ -524,6 +525,8 @@ class RTCStatsReportVerifier { } else { verifier.TestMemberIsNonNegative( media_stream_track.frames_sent); + verifier.TestMemberIsNonNegative( + media_stream_track.huge_frames_sent); verifier.TestMemberIsUndefined(media_stream_track.frames_received); verifier.TestMemberIsUndefined(media_stream_track.frames_decoded); verifier.TestMemberIsUndefined(media_stream_track.frames_dropped); @@ -546,6 +549,7 @@ class RTCStatsReportVerifier { verifier.TestMemberIsUndefined(media_stream_track.frame_height); verifier.TestMemberIsUndefined(media_stream_track.frames_per_second); verifier.TestMemberIsUndefined(media_stream_track.frames_sent); + verifier.TestMemberIsUndefined(media_stream_track.huge_frames_sent); verifier.TestMemberIsUndefined(media_stream_track.frames_received); verifier.TestMemberIsUndefined(media_stream_track.frames_decoded); verifier.TestMemberIsUndefined(media_stream_track.frames_dropped); diff --git a/pc/rtcstatscollector.cc b/pc/rtcstatscollector.cc index 80e67c5eb4..20cbc912a1 100644 --- a/pc/rtcstatscollector.cc +++ b/pc/rtcstatscollector.cc @@ -455,6 +455,7 @@ ProduceMediaStreamTrackStatsFromVideoSenderInfo( // TODO(hbos): Will reduce this by frames dropped due to congestion control // when available. https://crbug.com/659137 video_track_stats->frames_sent = video_sender_info.frames_encoded; + video_track_stats->huge_frames_sent = video_sender_info.huge_frames_sent; return video_track_stats; } diff --git a/pc/rtcstatscollector_unittest.cc b/pc/rtcstatscollector_unittest.cc index 224dc293b2..f180471a9b 100644 --- a/pc/rtcstatscollector_unittest.cc +++ b/pc/rtcstatscollector_unittest.cc @@ -1333,6 +1333,7 @@ TEST_F(RTCStatsCollectorTest, video_sender_info_ssrc1.send_frame_width = 1234; video_sender_info_ssrc1.send_frame_height = 4321; video_sender_info_ssrc1.frames_encoded = 11; + video_sender_info_ssrc1.huge_frames_sent = 1; stats_->CreateMockRtpSendersReceiversAndChannels( {}, {}, @@ -1367,6 +1368,7 @@ TEST_F(RTCStatsCollectorTest, expected_local_video_track_ssrc1.frame_width = 1234; expected_local_video_track_ssrc1.frame_height = 4321; expected_local_video_track_ssrc1.frames_sent = 11; + expected_local_video_track_ssrc1.huge_frames_sent = 1; ASSERT_TRUE(report->Get(expected_local_video_track_ssrc1.id())); EXPECT_EQ(expected_local_video_track_ssrc1, report->Get(expected_local_video_track_ssrc1.id()) diff --git a/pc/statscollector.cc b/pc/statscollector.cc index 3462b5cb8b..8807e61a90 100644 --- a/pc/statscollector.cc +++ b/pc/statscollector.cc @@ -313,20 +313,21 @@ void ExtractStats(const cricket::VideoSenderInfo& info, StatsReport* report) { report->AddInt(StatsReport::kStatsValueNameQpSum, *info.qp_sum); const IntForAdd ints[] = { - { StatsReport::kStatsValueNameAdaptationChanges, info.adapt_changes }, - { StatsReport::kStatsValueNameAvgEncodeMs, info.avg_encode_ms }, - { StatsReport::kStatsValueNameEncodeUsagePercent, - info.encode_usage_percent }, - { StatsReport::kStatsValueNameFirsReceived, info.firs_rcvd }, - { StatsReport::kStatsValueNameFrameHeightSent, info.send_frame_height }, - { StatsReport::kStatsValueNameFrameRateInput, info.framerate_input }, - { StatsReport::kStatsValueNameFrameRateSent, info.framerate_sent }, - { StatsReport::kStatsValueNameFrameWidthSent, info.send_frame_width }, - { StatsReport::kStatsValueNameNacksReceived, info.nacks_rcvd }, - { StatsReport::kStatsValueNamePacketsLost, info.packets_lost }, - { StatsReport::kStatsValueNamePacketsSent, info.packets_sent }, - { StatsReport::kStatsValueNamePlisReceived, info.plis_rcvd }, - { StatsReport::kStatsValueNameFramesEncoded, info.frames_encoded }, + {StatsReport::kStatsValueNameAdaptationChanges, info.adapt_changes}, + {StatsReport::kStatsValueNameAvgEncodeMs, info.avg_encode_ms}, + {StatsReport::kStatsValueNameEncodeUsagePercent, + info.encode_usage_percent}, + {StatsReport::kStatsValueNameFirsReceived, info.firs_rcvd}, + {StatsReport::kStatsValueNameFrameHeightSent, info.send_frame_height}, + {StatsReport::kStatsValueNameFrameRateInput, info.framerate_input}, + {StatsReport::kStatsValueNameFrameRateSent, info.framerate_sent}, + {StatsReport::kStatsValueNameFrameWidthSent, info.send_frame_width}, + {StatsReport::kStatsValueNameNacksReceived, info.nacks_rcvd}, + {StatsReport::kStatsValueNamePacketsLost, info.packets_lost}, + {StatsReport::kStatsValueNamePacketsSent, info.packets_sent}, + {StatsReport::kStatsValueNamePlisReceived, info.plis_rcvd}, + {StatsReport::kStatsValueNameFramesEncoded, info.frames_encoded}, + {StatsReport::kStatsValueNameHugeFramesSent, info.huge_frames_sent}, }; for (const auto& i : ints) diff --git a/stats/rtcstats_objects.cc b/stats/rtcstats_objects.cc index b6bc4c0f9e..0a176b4f64 100644 --- a/stats/rtcstats_objects.cc +++ b/stats/rtcstats_objects.cc @@ -383,6 +383,7 @@ WEBRTC_RTCSTATS_IMPL(RTCMediaStreamTrackStats, RTCStats, "track", &frame_height, &frames_per_second, &frames_sent, + &huge_frames_sent, &frames_received, &frames_decoded, &frames_dropped, @@ -418,6 +419,7 @@ RTCMediaStreamTrackStats::RTCMediaStreamTrackStats(std::string&& id, frame_height("frameHeight"), frames_per_second("framesPerSecond"), frames_sent("framesSent"), + huge_frames_sent("hugeFramesSent"), frames_received("framesReceived"), frames_decoded("framesDecoded"), frames_dropped("framesDropped"), @@ -449,6 +451,7 @@ RTCMediaStreamTrackStats::RTCMediaStreamTrackStats( frame_height(other.frame_height), frames_per_second(other.frames_per_second), frames_sent(other.frames_sent), + huge_frames_sent(other.huge_frames_sent), frames_received(other.frames_received), frames_decoded(other.frames_decoded), frames_dropped(other.frames_dropped), diff --git a/video/send_statistics_proxy.cc b/video/send_statistics_proxy.cc index 96cb501e1d..36b63313e6 100644 --- a/video/send_statistics_proxy.cc +++ b/video/send_statistics_proxy.cc @@ -914,6 +914,17 @@ void SendStatisticsProxy::OnSendEncodedImage( } } + // If any of the simulcast streams have a huge frame, it should be counted + // as a single difficult input frame. + // https://w3c.github.io/webrtc-stats/#dom-rtcvideosenderstats-hugeframessent + if (encoded_image.timing_.flags & TimingFrameFlags::kTriggeredBySize) { + if (!last_outlier_timestamp_ || + *last_outlier_timestamp_ < encoded_image.capture_time_ms_) { + last_outlier_timestamp_.emplace(encoded_image.capture_time_ms_); + ++stats_.huge_frames_sent; + } + } + media_byte_rate_tracker_.AddSamples(encoded_image._length); // Initialize to current since |is_limited_in_resolution| is only updated diff --git a/video/send_statistics_proxy.h b/video/send_statistics_proxy.h index 1aa836ebca..61d69bda5e 100644 --- a/video/send_statistics_proxy.h +++ b/video/send_statistics_proxy.h @@ -249,6 +249,8 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver, rtc::RateTracker media_byte_rate_tracker_ RTC_GUARDED_BY(crit_); rtc::RateTracker encoded_frame_rate_tracker_ RTC_GUARDED_BY(crit_); + rtc::Optional last_outlier_timestamp_ RTC_GUARDED_BY(crit_); + // Contains stats used for UMA histograms. These stats will be reset if // content type changes between real-time video and screenshare, since these // will be reported separately.