Add jitterBufferDelay and jitterBufferEmittedCount stats for video

Bug: webrtc:10450
Change-Id: I6f586a3c6781450b9bfdcc31dc3f49f6289d70e0
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/138265
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Magnus Flodman <mflodman@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28096}
This commit is contained in:
Guido Urdaneta 2019-05-28 17:38:08 +02:00 committed by Commit Bot
parent e4470cd8b4
commit 6737841533
9 changed files with 108 additions and 66 deletions

View File

@ -53,6 +53,8 @@ std::string VideoReceiveStream::Stats::ToString(int64_t time_ms) const {
ss << "cur_delay_ms: " << current_delay_ms << ", ";
ss << "targ_delay_ms: " << target_delay_ms << ", ";
ss << "jb_delay_ms: " << jitter_buffer_ms << ", ";
ss << "jb_cumulative_delay_seconds: " << jitter_buffer_delay_seconds << ", ";
ss << "jb_emitted_count: " << jitter_buffer_emitted_count << ", ";
ss << "min_playout_delay_ms: " << min_playout_delay_ms << ", ";
ss << "sync_offset_ms: " << sync_offset_ms << ", ";
ss << "cum_loss: " << rtcp_stats.packets_lost << ", ";

View File

@ -77,6 +77,10 @@ class VideoReceiveStream {
int current_delay_ms = 0;
int target_delay_ms = 0;
int jitter_buffer_ms = 0;
// https://w3c.github.io/webrtc-stats/#dom-rtcvideoreceiverstats-jitterbufferdelay
double jitter_buffer_delay_seconds = 0;
// https://w3c.github.io/webrtc-stats/#dom-rtcvideoreceiverstats-jitterbufferemittedcount
uint64_t jitter_buffer_emitted_count = 0;
int min_playout_delay_ms = 0;
int render_delay_ms = 10;
int64_t interframe_delay_max_ms = -1;

View File

@ -617,6 +617,12 @@ struct VideoReceiverInfo : public MediaReceiverInfo {
int max_decode_ms = 0;
// Jitter (network-related) latency.
int jitter_buffer_ms = 0;
// Jitter (network-related) latency (cumulative).
// https://w3c.github.io/webrtc-stats/#dom-rtcvideoreceiverstats-jitterbufferdelay
double jitter_buffer_delay_seconds = 0;
// Number of observations for cumulative jitter latency.
// https://w3c.github.io/webrtc-stats/#dom-rtcvideoreceiverstats-jitterbufferemittedcount
uint64_t jitter_buffer_emitted_count = 0;
// Requested minimum playout latency.
int min_playout_delay_ms = 0;
// Requested latency to account for rendering delay.

View File

@ -2734,6 +2734,8 @@ WebRtcVideoChannel::WebRtcVideoReceiveStream::GetVideoReceiverInfo(
info.current_delay_ms = stats.current_delay_ms;
info.target_delay_ms = stats.target_delay_ms;
info.jitter_buffer_ms = stats.jitter_buffer_ms;
info.jitter_buffer_delay_seconds = stats.jitter_buffer_delay_seconds;
info.jitter_buffer_emitted_count = stats.jitter_buffer_emitted_count;
info.min_playout_delay_ms = stats.min_playout_delay_ms;
info.render_delay_ms = stats.render_delay_ms;
info.frames_received =

View File

@ -5000,6 +5000,8 @@ TEST_F(WebRtcVideoChannelTest, GetStatsTranslatesDecodeStatsCorrectly) {
stats.current_delay_ms = 4;
stats.target_delay_ms = 5;
stats.jitter_buffer_ms = 6;
stats.jitter_buffer_delay_seconds = 60;
stats.jitter_buffer_emitted_count = 6;
stats.min_playout_delay_ms = 7;
stats.render_delay_ms = 8;
stats.width = 9;
@ -5020,6 +5022,10 @@ TEST_F(WebRtcVideoChannelTest, GetStatsTranslatesDecodeStatsCorrectly) {
EXPECT_EQ(stats.current_delay_ms, info.receivers[0].current_delay_ms);
EXPECT_EQ(stats.target_delay_ms, info.receivers[0].target_delay_ms);
EXPECT_EQ(stats.jitter_buffer_ms, info.receivers[0].jitter_buffer_ms);
EXPECT_EQ(stats.jitter_buffer_delay_seconds,
info.receivers[0].jitter_buffer_delay_seconds);
EXPECT_EQ(stats.jitter_buffer_emitted_count,
info.receivers[0].jitter_buffer_emitted_count);
EXPECT_EQ(stats.min_playout_delay_ms, info.receivers[0].min_playout_delay_ms);
EXPECT_EQ(stats.render_delay_ms, info.receivers[0].render_delay_ms);
EXPECT_EQ(stats.width, info.receivers[0].frame_width);

View File

@ -675,6 +675,10 @@ ProduceMediaStreamTrackStatsFromVideoReceiverInfo(
video_track_stats->frame_height = static_cast<uint32_t>(
video_receiver_info.frame_height);
}
video_track_stats->jitter_buffer_delay =
video_receiver_info.jitter_buffer_delay_seconds;
video_track_stats->jitter_buffer_emitted_count =
video_receiver_info.jitter_buffer_emitted_count;
video_track_stats->frames_received = video_receiver_info.frames_received;
// TODO(hbos): When we support receiving simulcast, this should be the total
// number of frames correctly decoded, independent of which SSRC it was

View File

@ -1647,6 +1647,8 @@ TEST_F(RTCStatsCollectorTest,
video_receiver_info_ssrc3.local_stats[0].ssrc = 3;
video_receiver_info_ssrc3.frame_width = 6789;
video_receiver_info_ssrc3.frame_height = 9876;
video_receiver_info_ssrc3.jitter_buffer_delay_seconds = 2.5;
video_receiver_info_ssrc3.jitter_buffer_emitted_count = 25;
video_receiver_info_ssrc3.frames_received = 1000;
video_receiver_info_ssrc3.frames_decoded = 995;
video_receiver_info_ssrc3.frames_rendered = 990;
@ -1694,6 +1696,8 @@ TEST_F(RTCStatsCollectorTest,
expected_remote_video_track_ssrc3.detached = false;
expected_remote_video_track_ssrc3.frame_width = 6789;
expected_remote_video_track_ssrc3.frame_height = 9876;
expected_remote_video_track_ssrc3.jitter_buffer_delay = 2.5;
expected_remote_video_track_ssrc3.jitter_buffer_emitted_count = 25;
expected_remote_video_track_ssrc3.frames_received = 1000;
expected_remote_video_track_ssrc3.frames_decoded = 995;
expected_remote_video_track_ssrc3.frames_dropped = 1000 - 990;

View File

@ -555,24 +555,16 @@ class RTCStatsReportVerifier {
verifier.TestMemberIsDefined(media_stream_track.ended);
verifier.TestMemberIsDefined(media_stream_track.detached);
verifier.TestMemberIsDefined(media_stream_track.kind);
RTC_DCHECK(media_stream_track.remote_source.is_defined());
// Video or audio media stream track?
if (*media_stream_track.kind == RTCMediaStreamTrackKind::kVideo) {
// The type of the referenced media source depends on kind.
if (media_stream_track.remote_source.is_defined() &&
!*media_stream_track.remote_source) {
verifier.TestMemberIsIDReference(media_stream_track.media_source_id,
RTCVideoSourceStats::kType);
} else {
// Remote tracks don't have media source stats.
verifier.TestMemberIsUndefined(media_stream_track.media_source_id);
}
// Video-only members
verifier.TestMemberIsNonNegative<uint32_t>(
media_stream_track.frame_width);
verifier.TestMemberIsNonNegative<uint32_t>(
media_stream_track.frame_height);
verifier.TestMemberIsUndefined(media_stream_track.frames_per_second);
if (*media_stream_track.remote_source) {
verifier.TestMemberIsUndefined(media_stream_track.media_source_id);
verifier.TestMemberIsNonNegative<double>(
media_stream_track.jitter_buffer_delay);
verifier.TestMemberIsNonNegative<uint64_t>(
media_stream_track.jitter_buffer_emitted_count);
verifier.TestMemberIsUndefined(media_stream_track.frames_sent);
verifier.TestMemberIsUndefined(media_stream_track.huge_frames_sent);
verifier.TestMemberIsNonNegative<uint32_t>(
@ -594,6 +586,12 @@ class RTCStatsReportVerifier {
verifier.TestMemberIsNonNegative<double>(
media_stream_track.sum_squared_frame_durations);
} else {
verifier.TestMemberIsIDReference(media_stream_track.media_source_id,
RTCVideoSourceStats::kType);
// Local tracks have no jitter buffer.
verifier.TestMemberIsUndefined(media_stream_track.jitter_buffer_delay);
verifier.TestMemberIsUndefined(
media_stream_track.jitter_buffer_emitted_count);
verifier.TestMemberIsNonNegative<uint32_t>(
media_stream_track.frames_sent);
verifier.TestMemberIsNonNegative<uint32_t>(
@ -612,6 +610,12 @@ class RTCStatsReportVerifier {
verifier.TestMemberIsUndefined(
media_stream_track.sum_squared_frame_durations);
}
// Video-only members
verifier.TestMemberIsNonNegative<uint32_t>(
media_stream_track.frame_width);
verifier.TestMemberIsNonNegative<uint32_t>(
media_stream_track.frame_height);
verifier.TestMemberIsUndefined(media_stream_track.frames_per_second);
verifier.TestMemberIsUndefined(media_stream_track.frames_corrupted);
verifier.TestMemberIsUndefined(media_stream_track.partial_frames_lost);
verifier.TestMemberIsUndefined(media_stream_track.full_frames_lost);
@ -622,16 +626,69 @@ class RTCStatsReportVerifier {
media_stream_track.echo_return_loss_enhancement);
verifier.TestMemberIsUndefined(media_stream_track.total_audio_energy);
verifier.TestMemberIsUndefined(media_stream_track.total_samples_duration);
verifier.TestMemberIsUndefined(media_stream_track.total_samples_received);
verifier.TestMemberIsUndefined(media_stream_track.concealed_samples);
verifier.TestMemberIsUndefined(media_stream_track.concealment_events);
verifier.TestMemberIsUndefined(media_stream_track.jitter_buffer_flushes);
verifier.TestMemberIsUndefined(
media_stream_track.delayed_packet_outage_samples);
verifier.TestMemberIsUndefined(
media_stream_track.relative_packet_arrival_delay);
verifier.TestMemberIsUndefined(media_stream_track.interruption_count);
verifier.TestMemberIsUndefined(
media_stream_track.total_interruption_duration);
} else {
RTC_DCHECK_EQ(*media_stream_track.kind, RTCMediaStreamTrackKind::kAudio);
// The type of the referenced media source depends on kind.
if (media_stream_track.remote_source.is_defined() &&
!*media_stream_track.remote_source) {
verifier.TestMemberIsIDReference(media_stream_track.media_source_id,
RTCAudioSourceStats::kType);
} else {
if (*media_stream_track.remote_source) {
// Remote tracks don't have media source stats.
verifier.TestMemberIsUndefined(media_stream_track.media_source_id);
verifier.TestMemberIsNonNegative<double>(
media_stream_track.jitter_buffer_delay);
verifier.TestMemberIsNonNegative<uint64_t>(
media_stream_track.jitter_buffer_emitted_count);
verifier.TestMemberIsNonNegative<uint64_t>(
media_stream_track.total_samples_received);
verifier.TestMemberIsNonNegative<uint64_t>(
media_stream_track.concealed_samples);
verifier.TestMemberIsNonNegative<uint64_t>(
media_stream_track.concealment_events);
verifier.TestMemberIsNonNegative<uint64_t>(
media_stream_track.inserted_samples_for_deceleration);
verifier.TestMemberIsNonNegative<uint64_t>(
media_stream_track.removed_samples_for_acceleration);
verifier.TestMemberIsNonNegative<uint64_t>(
media_stream_track.silent_concealed_samples);
verifier.TestMemberIsNonNegative<uint64_t>(
media_stream_track.jitter_buffer_flushes);
verifier.TestMemberIsNonNegative<uint64_t>(
media_stream_track.delayed_packet_outage_samples);
verifier.TestMemberIsNonNegative<double>(
media_stream_track.relative_packet_arrival_delay);
verifier.TestMemberIsNonNegative<uint32_t>(
media_stream_track.interruption_count);
verifier.TestMemberIsNonNegative<double>(
media_stream_track.total_interruption_duration);
} else {
verifier.TestMemberIsIDReference(media_stream_track.media_source_id,
RTCAudioSourceStats::kType);
// Local audio tracks have no jitter buffer.
verifier.TestMemberIsUndefined(media_stream_track.jitter_buffer_delay);
verifier.TestMemberIsUndefined(
media_stream_track.jitter_buffer_emitted_count);
verifier.TestMemberIsUndefined(
media_stream_track.total_samples_received);
verifier.TestMemberIsUndefined(media_stream_track.concealed_samples);
verifier.TestMemberIsUndefined(media_stream_track.concealment_events);
verifier.TestMemberIsUndefined(
media_stream_track.jitter_buffer_flushes);
verifier.TestMemberIsUndefined(
media_stream_track.delayed_packet_outage_samples);
verifier.TestMemberIsUndefined(
media_stream_track.relative_packet_arrival_delay);
verifier.TestMemberIsUndefined(media_stream_track.interruption_count);
verifier.TestMemberIsUndefined(
media_stream_track.total_interruption_duration);
}
// Video-only members should be undefined
verifier.TestMemberIsUndefined(media_stream_track.frame_width);
@ -666,53 +723,6 @@ class RTCStatsReportVerifier {
verifier.MarkMemberTested(media_stream_track.echo_return_loss_enhancement,
true);
}
// totalSamplesReceived, concealedSamples and concealmentEvents are only
// present on inbound audio tracks.
// jitterBufferDelay is currently only implemented for audio.
if (*media_stream_track.kind == RTCMediaStreamTrackKind::kAudio &&
*media_stream_track.remote_source) {
verifier.TestMemberIsNonNegative<double>(
media_stream_track.jitter_buffer_delay);
verifier.TestMemberIsNonNegative<uint64_t>(
media_stream_track.jitter_buffer_emitted_count);
verifier.TestMemberIsNonNegative<uint64_t>(
media_stream_track.total_samples_received);
verifier.TestMemberIsNonNegative<uint64_t>(
media_stream_track.concealed_samples);
verifier.TestMemberIsNonNegative<uint64_t>(
media_stream_track.concealment_events);
verifier.TestMemberIsNonNegative<uint64_t>(
media_stream_track.inserted_samples_for_deceleration);
verifier.TestMemberIsNonNegative<uint64_t>(
media_stream_track.removed_samples_for_acceleration);
verifier.TestMemberIsNonNegative<uint64_t>(
media_stream_track.silent_concealed_samples);
verifier.TestMemberIsNonNegative<uint64_t>(
media_stream_track.jitter_buffer_flushes);
verifier.TestMemberIsNonNegative<uint64_t>(
media_stream_track.delayed_packet_outage_samples);
verifier.TestMemberIsNonNegative<double>(
media_stream_track.relative_packet_arrival_delay);
verifier.TestMemberIsNonNegative<uint32_t>(
media_stream_track.interruption_count);
verifier.TestMemberIsNonNegative<double>(
media_stream_track.total_interruption_duration);
} else {
verifier.TestMemberIsUndefined(media_stream_track.jitter_buffer_delay);
verifier.TestMemberIsUndefined(
media_stream_track.jitter_buffer_emitted_count);
verifier.TestMemberIsUndefined(media_stream_track.total_samples_received);
verifier.TestMemberIsUndefined(media_stream_track.concealed_samples);
verifier.TestMemberIsUndefined(media_stream_track.concealment_events);
verifier.TestMemberIsUndefined(media_stream_track.jitter_buffer_flushes);
verifier.TestMemberIsUndefined(
media_stream_track.delayed_packet_outage_samples);
verifier.TestMemberIsUndefined(
media_stream_track.relative_packet_arrival_delay);
verifier.TestMemberIsUndefined(media_stream_track.interruption_count);
verifier.TestMemberIsUndefined(
media_stream_track.total_interruption_duration);
}
return verifier.ExpectAllMembersSuccessfullyTested();
}

View File

@ -596,6 +596,10 @@ VideoReceiveStream::Stats ReceiveStatisticsProxy::GetStats() const {
video_quality_observer_->SumSquaredFrameDurationsSec();
stats_.content_type = last_content_type_;
stats_.timing_frame_info = timing_frame_info_counter_.Max(now_ms);
stats_.jitter_buffer_delay_seconds =
static_cast<double>(current_delay_counter_.Sum(1).value_or(0)) /
rtc::kNumMillisecsPerSec;
stats_.jitter_buffer_emitted_count = current_delay_counter_.NumSamples();
return stats_;
}