Add totalInterFrameDelay to RTCInboundRTPStreamStats
Bug: webrtc:11108 Change-Id: I0e0168ba303b127a8db3946d5fa5f97a1c90fb27 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/160042 Reviewed-by: Niels Moller <nisse@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Henrik Boström <hbos@webrtc.org> Commit-Queue: Johannes Kron <kron@webrtc.org> Cr-Commit-Position: refs/heads/master@{#29894}
This commit is contained in:
parent
429d8fe28b
commit
00376e190a
@ -444,6 +444,8 @@ class RTC_EXPORT RTCInboundRTPStreamStats final : public RTCRTPStreamStats {
|
||||
RTCStatsMember<uint32_t> frames_decoded;
|
||||
RTCStatsMember<uint32_t> key_frames_decoded;
|
||||
RTCStatsMember<double> total_decode_time;
|
||||
RTCStatsMember<double> total_inter_frame_delay;
|
||||
RTCStatsMember<double> total_squared_inter_frame_delay;
|
||||
// https://henbos.github.io/webrtc-provisional-stats/#dom-rtcinboundrtpstreamstats-contenttype
|
||||
RTCStatsMember<std::string> content_type;
|
||||
// TODO(asapersson): Currently only populated if audio/video sync is enabled.
|
||||
|
||||
@ -91,6 +91,12 @@ class VideoReceiveStream {
|
||||
uint32_t frames_decoded = 0;
|
||||
// https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats-totaldecodetime
|
||||
uint64_t total_decode_time_ms = 0;
|
||||
// Total inter frame delay in seconds.
|
||||
// https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats-totalinterframedelay
|
||||
double total_inter_frame_delay = 0;
|
||||
// Total squared inter frame delay in seconds^2.
|
||||
// https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats-totalsqauredinterframedelay
|
||||
double total_squared_inter_frame_delay = 0;
|
||||
int64_t first_frame_received_to_decoded_ms = -1;
|
||||
absl::optional<uint64_t> qp_sum;
|
||||
|
||||
|
||||
@ -613,6 +613,8 @@ struct VideoReceiverInfo : public MediaReceiverInfo {
|
||||
absl::optional<uint64_t> qp_sum;
|
||||
// https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats-totaldecodetime
|
||||
uint64_t total_decode_time_ms = 0;
|
||||
double total_inter_frame_delay = 0;
|
||||
double total_squared_inter_frame_delay = 0;
|
||||
int64_t interframe_delay_max_ms = -1;
|
||||
uint32_t freeze_count = 0;
|
||||
uint32_t pause_count = 0;
|
||||
|
||||
@ -2846,6 +2846,8 @@ WebRtcVideoChannel::WebRtcVideoReceiveStream::GetVideoReceiverInfo(
|
||||
stats.estimated_playout_ntp_timestamp_ms;
|
||||
info.first_frame_received_to_decoded_ms =
|
||||
stats.first_frame_received_to_decoded_ms;
|
||||
info.total_inter_frame_delay = stats.total_inter_frame_delay;
|
||||
info.total_squared_inter_frame_delay = stats.total_squared_inter_frame_delay;
|
||||
info.interframe_delay_max_ms = stats.interframe_delay_max_ms;
|
||||
info.freeze_count = stats.freeze_count;
|
||||
info.pause_count = stats.pause_count;
|
||||
|
||||
@ -5279,6 +5279,22 @@ TEST_F(WebRtcVideoChannelTest, GetStatsTranslatesDecodeStatsCorrectly) {
|
||||
EXPECT_EQ(stats.total_decode_time_ms, info.receivers[0].total_decode_time_ms);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoChannelTest,
|
||||
GetStatsTranslatesInterFrameDelayStatsCorrectly) {
|
||||
FakeVideoReceiveStream* stream = AddRecvStream();
|
||||
webrtc::VideoReceiveStream::Stats stats;
|
||||
stats.total_inter_frame_delay = 0.123;
|
||||
stats.total_squared_inter_frame_delay = 0.00456;
|
||||
stream->SetStats(stats);
|
||||
|
||||
cricket::VideoMediaInfo info;
|
||||
ASSERT_TRUE(channel_->GetStats(&info));
|
||||
EXPECT_EQ(stats.total_inter_frame_delay,
|
||||
info.receivers[0].total_inter_frame_delay);
|
||||
EXPECT_EQ(stats.total_squared_inter_frame_delay,
|
||||
info.receivers[0].total_squared_inter_frame_delay);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoChannelTest, GetStatsTranslatesReceivePacketStatsCorrectly) {
|
||||
FakeVideoReceiveStream* stream = AddRecvStream();
|
||||
webrtc::VideoReceiveStream::Stats stats;
|
||||
|
||||
@ -320,6 +320,10 @@ void SetInboundRTPStreamStatsFromVideoReceiverInfo(
|
||||
inbound_video->total_decode_time =
|
||||
static_cast<double>(video_receiver_info.total_decode_time_ms) /
|
||||
rtc::kNumMillisecsPerSec;
|
||||
inbound_video->total_inter_frame_delay =
|
||||
video_receiver_info.total_inter_frame_delay;
|
||||
inbound_video->total_squared_inter_frame_delay =
|
||||
video_receiver_info.total_squared_inter_frame_delay;
|
||||
if (video_receiver_info.last_packet_received_timestamp_ms) {
|
||||
inbound_video->last_packet_received_timestamp =
|
||||
static_cast<double>(
|
||||
|
||||
@ -1823,6 +1823,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) {
|
||||
video_media_info.receivers[0].key_frames_decoded = 3;
|
||||
video_media_info.receivers[0].qp_sum = absl::nullopt;
|
||||
video_media_info.receivers[0].total_decode_time_ms = 9000;
|
||||
video_media_info.receivers[0].total_inter_frame_delay = 0.123;
|
||||
video_media_info.receivers[0].total_squared_inter_frame_delay = 0.00456;
|
||||
|
||||
video_media_info.receivers[0].last_packet_received_timestamp_ms =
|
||||
absl::nullopt;
|
||||
video_media_info.receivers[0].content_type = VideoContentType::UNSPECIFIED;
|
||||
@ -1865,6 +1868,8 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) {
|
||||
expected_video.key_frames_decoded = 3;
|
||||
// |expected_video.qp_sum| should be undefined.
|
||||
expected_video.total_decode_time = 9.0;
|
||||
expected_video.total_inter_frame_delay = 0.123;
|
||||
expected_video.total_squared_inter_frame_delay = 0.00456;
|
||||
// |expected_video.last_packet_received_timestamp| should be undefined.
|
||||
// |expected_video.content_type| should be undefined.
|
||||
// |expected_video.decoder_implementation| should be undefined.
|
||||
|
||||
@ -830,6 +830,10 @@ class RTCStatsReportVerifier {
|
||||
verifier.TestMemberIsDefined(inbound_stream.key_frames_decoded);
|
||||
verifier.TestMemberIsNonNegative<double>(
|
||||
inbound_stream.total_decode_time);
|
||||
verifier.TestMemberIsNonNegative<double>(
|
||||
inbound_stream.total_inter_frame_delay);
|
||||
verifier.TestMemberIsNonNegative<double>(
|
||||
inbound_stream.total_squared_inter_frame_delay);
|
||||
// The integration test is not set up to test screen share; don't require
|
||||
// this to be present.
|
||||
verifier.MarkMemberTested(inbound_stream.content_type, true);
|
||||
@ -837,6 +841,9 @@ class RTCStatsReportVerifier {
|
||||
verifier.TestMemberIsUndefined(inbound_stream.frames_decoded);
|
||||
verifier.TestMemberIsUndefined(inbound_stream.key_frames_decoded);
|
||||
verifier.TestMemberIsUndefined(inbound_stream.total_decode_time);
|
||||
verifier.TestMemberIsUndefined(inbound_stream.total_inter_frame_delay);
|
||||
verifier.TestMemberIsUndefined(
|
||||
inbound_stream.total_squared_inter_frame_delay);
|
||||
verifier.TestMemberIsUndefined(inbound_stream.content_type);
|
||||
}
|
||||
return verifier.ExpectAllMembersSuccessfullyTested();
|
||||
|
||||
@ -616,6 +616,8 @@ WEBRTC_RTCSTATS_IMPL(
|
||||
&frames_decoded,
|
||||
&key_frames_decoded,
|
||||
&total_decode_time,
|
||||
&total_inter_frame_delay,
|
||||
&total_squared_inter_frame_delay,
|
||||
&content_type,
|
||||
&estimated_playout_timestamp,
|
||||
&decoder_implementation)
|
||||
@ -650,6 +652,8 @@ RTCInboundRTPStreamStats::RTCInboundRTPStreamStats(std::string&& id,
|
||||
frames_decoded("framesDecoded"),
|
||||
key_frames_decoded("keyFramesDecoded"),
|
||||
total_decode_time("totalDecodeTime"),
|
||||
total_inter_frame_delay("totalInterFrameDelay"),
|
||||
total_squared_inter_frame_delay("totalSquaredInterFrameDelay"),
|
||||
content_type("contentType"),
|
||||
estimated_playout_timestamp("estimatedPlayoutTimestamp"),
|
||||
decoder_implementation("decoderImplementation") {}
|
||||
@ -679,6 +683,8 @@ RTCInboundRTPStreamStats::RTCInboundRTPStreamStats(
|
||||
frames_decoded(other.frames_decoded),
|
||||
key_frames_decoded(other.key_frames_decoded),
|
||||
total_decode_time(other.total_decode_time),
|
||||
total_inter_frame_delay(other.total_inter_frame_delay),
|
||||
total_squared_inter_frame_delay(other.total_squared_inter_frame_delay),
|
||||
content_type(other.content_type),
|
||||
estimated_playout_timestamp(other.estimated_playout_timestamp),
|
||||
decoder_implementation(other.decoder_implementation) {}
|
||||
|
||||
@ -777,6 +777,10 @@ void ReceiveStatisticsProxy::OnDecodedFrame(const VideoFrame& frame,
|
||||
if (last_decoded_frame_time_ms_) {
|
||||
int64_t interframe_delay_ms = now_ms - *last_decoded_frame_time_ms_;
|
||||
RTC_DCHECK_GE(interframe_delay_ms, 0);
|
||||
double interframe_delay = interframe_delay_ms / 1000.0;
|
||||
stats_.total_inter_frame_delay += interframe_delay;
|
||||
stats_.total_squared_inter_frame_delay +=
|
||||
interframe_delay * interframe_delay;
|
||||
interframe_delay_max_moving_.Add(interframe_delay_ms, now_ms);
|
||||
content_specific_stats->interframe_delay_counter.Add(interframe_delay_ms);
|
||||
content_specific_stats->interframe_delay_percentiles.Add(
|
||||
|
||||
@ -184,6 +184,63 @@ TEST_F(ReceiveStatisticsProxyTest, ReportsContentType) {
|
||||
statistics_proxy_->GetStats().content_type));
|
||||
}
|
||||
|
||||
TEST_F(ReceiveStatisticsProxyTest, ReportsMaxTotalInterFrameDelay) {
|
||||
webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
|
||||
const TimeDelta kInterFrameDelay1 = TimeDelta::ms(100);
|
||||
const TimeDelta kInterFrameDelay2 = TimeDelta::ms(200);
|
||||
const TimeDelta kInterFrameDelay3 = TimeDelta::ms(300);
|
||||
double expected_total_inter_frame_delay = 0;
|
||||
double expected_total_squared_inter_frame_delay = 0;
|
||||
EXPECT_EQ(expected_total_inter_frame_delay,
|
||||
statistics_proxy_->GetStats().total_inter_frame_delay);
|
||||
EXPECT_EQ(expected_total_squared_inter_frame_delay,
|
||||
statistics_proxy_->GetStats().total_squared_inter_frame_delay);
|
||||
|
||||
statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
|
||||
VideoContentType::UNSPECIFIED);
|
||||
EXPECT_DOUBLE_EQ(expected_total_inter_frame_delay,
|
||||
statistics_proxy_->GetStats().total_inter_frame_delay);
|
||||
EXPECT_DOUBLE_EQ(
|
||||
expected_total_squared_inter_frame_delay,
|
||||
statistics_proxy_->GetStats().total_squared_inter_frame_delay);
|
||||
|
||||
fake_clock_.AdvanceTime(kInterFrameDelay1);
|
||||
statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
|
||||
VideoContentType::UNSPECIFIED);
|
||||
expected_total_inter_frame_delay += kInterFrameDelay1.seconds<double>();
|
||||
expected_total_squared_inter_frame_delay +=
|
||||
pow(kInterFrameDelay1.seconds<double>(), 2.0);
|
||||
EXPECT_DOUBLE_EQ(expected_total_inter_frame_delay,
|
||||
statistics_proxy_->GetStats().total_inter_frame_delay);
|
||||
EXPECT_DOUBLE_EQ(
|
||||
expected_total_squared_inter_frame_delay,
|
||||
statistics_proxy_->GetStats().total_squared_inter_frame_delay);
|
||||
|
||||
fake_clock_.AdvanceTime(kInterFrameDelay2);
|
||||
statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
|
||||
VideoContentType::UNSPECIFIED);
|
||||
expected_total_inter_frame_delay += kInterFrameDelay2.seconds<double>();
|
||||
expected_total_squared_inter_frame_delay +=
|
||||
pow(kInterFrameDelay2.seconds<double>(), 2.0);
|
||||
EXPECT_DOUBLE_EQ(expected_total_inter_frame_delay,
|
||||
statistics_proxy_->GetStats().total_inter_frame_delay);
|
||||
EXPECT_DOUBLE_EQ(
|
||||
expected_total_squared_inter_frame_delay,
|
||||
statistics_proxy_->GetStats().total_squared_inter_frame_delay);
|
||||
|
||||
fake_clock_.AdvanceTime(kInterFrameDelay3);
|
||||
statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
|
||||
VideoContentType::UNSPECIFIED);
|
||||
expected_total_inter_frame_delay += kInterFrameDelay3.seconds<double>();
|
||||
expected_total_squared_inter_frame_delay +=
|
||||
pow(kInterFrameDelay3.seconds<double>(), 2.0);
|
||||
EXPECT_DOUBLE_EQ(expected_total_inter_frame_delay,
|
||||
statistics_proxy_->GetStats().total_inter_frame_delay);
|
||||
EXPECT_DOUBLE_EQ(
|
||||
expected_total_squared_inter_frame_delay,
|
||||
statistics_proxy_->GetStats().total_squared_inter_frame_delay);
|
||||
}
|
||||
|
||||
TEST_F(ReceiveStatisticsProxyTest, ReportsMaxInterframeDelay) {
|
||||
webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
|
||||
const int64_t kInterframeDelayMs1 = 100;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user