diff --git a/api/stats/rtcstats_objects.h b/api/stats/rtcstats_objects.h index 81ec084f16..4ddfa93618 100644 --- a/api/stats/rtcstats_objects.h +++ b/api/stats/rtcstats_objects.h @@ -442,7 +442,9 @@ class RTC_EXPORT RTCOutboundRTPStreamStats final : public RTCRTPStreamStats { ~RTCOutboundRTPStreamStats() override; RTCStatsMember packets_sent; + RTCStatsMember retransmitted_packets_sent; RTCStatsMember bytes_sent; + RTCStatsMember retransmitted_bytes_sent; // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7066 RTCStatsMember target_bitrate; RTCStatsMember frames_encoded; diff --git a/audio/audio_send_stream.cc b/audio/audio_send_stream.cc index 7804f550b5..283fd9a603 100644 --- a/audio/audio_send_stream.cc +++ b/audio/audio_send_stream.cc @@ -389,7 +389,9 @@ webrtc::AudioSendStream::Stats AudioSendStream::GetStats( webrtc::CallSendStatistics call_stats = channel_send_->GetRTCPStatistics(); stats.bytes_sent = call_stats.bytesSent; + stats.retransmitted_bytes_sent = call_stats.retransmitted_bytes_sent; stats.packets_sent = call_stats.packetsSent; + stats.retransmitted_packets_sent = call_stats.retransmitted_packets_sent; // RTT isn't known until a RTCP report is received. Until then, VoiceEngine // returns 0 to indicate an error value. if (call_stats.rttMs > 0) { diff --git a/audio/channel_send.cc b/audio/channel_send.cc index 4e0094e70a..99e3f9032d 100644 --- a/audio/channel_send.cc +++ b/audio/channel_send.cc @@ -1070,17 +1070,22 @@ CallSendStatistics ChannelSend::GetRTCPStatistics() const { CallSendStatistics stats = {0}; stats.rttMs = GetRTT(); - size_t bytesSent(0); - uint32_t packetsSent(0); - - if (_rtpRtcpModule->DataCountersRTP(&bytesSent, &packetsSent) != 0) { - RTC_DLOG(LS_WARNING) - << "GetRTPStatistics() failed to retrieve RTP datacounters" - << " => output will not be complete"; - } - - stats.bytesSent = bytesSent; - stats.packetsSent = packetsSent; + StreamDataCounters rtp_stats; + StreamDataCounters rtx_stats; + _rtpRtcpModule->GetSendStreamDataCounters(&rtp_stats, &rtx_stats); + // TODO(https://crbug.com/webrtc/10525): Bytes sent should only include + // payload bytes, not header and padding bytes. + stats.bytesSent = + rtp_stats.transmitted.payload_bytes + + rtp_stats.transmitted.padding_bytes + rtp_stats.transmitted.header_bytes + + rtx_stats.transmitted.payload_bytes + + rtx_stats.transmitted.padding_bytes + rtx_stats.transmitted.header_bytes; + // TODO(https://crbug.com/webrtc/10555): RTX retransmissions should show up in + // separate outbound-rtp stream objects. + stats.retransmitted_bytes_sent = rtp_stats.retransmitted.payload_bytes; + stats.packetsSent = + rtp_stats.transmitted.packets + rtx_stats.transmitted.packets; + stats.retransmitted_packets_sent = rtp_stats.retransmitted.packets; return stats; } diff --git a/audio/channel_send.h b/audio/channel_send.h index 761e4b2566..45f7b1e304 100644 --- a/audio/channel_send.h +++ b/audio/channel_send.h @@ -35,7 +35,11 @@ class RtpTransportControllerSendInterface; struct CallSendStatistics { int64_t rttMs; size_t bytesSent; + // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-retransmittedbytessent + uint64_t retransmitted_bytes_sent; int packetsSent; + // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-retransmittedpacketssent + uint64_t retransmitted_packets_sent; }; // See section 6.4.2 in http://www.ietf.org/rfc/rfc3550.txt for details. diff --git a/call/audio_send_stream.h b/call/audio_send_stream.h index 08a50c850c..7e17b7c25b 100644 --- a/call/audio_send_stream.h +++ b/call/audio_send_stream.h @@ -42,7 +42,11 @@ class AudioSendStream { // TODO(solenberg): Harmonize naming and defaults with receive stream stats. uint32_t local_ssrc = 0; int64_t bytes_sent = 0; + // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-retransmittedbytessent + uint64_t retransmitted_bytes_sent = 0; int32_t packets_sent = 0; + // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-retransmittedpacketssent + uint64_t retransmitted_packets_sent = 0; int32_t packets_lost = -1; float fraction_lost = -1.0f; std::string codec_name; diff --git a/media/base/media_channel.h b/media/base/media_channel.h index c21f89e5d8..710fd1a713 100644 --- a/media/base/media_channel.h +++ b/media/base/media_channel.h @@ -387,7 +387,11 @@ struct MediaSenderInfo { } } int64_t bytes_sent = 0; + // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-retransmittedbytessent + uint64_t retransmitted_bytes_sent = 0; int packets_sent = 0; + // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-retransmittedpacketssent + uint64_t retransmitted_packets_sent = 0; int packets_lost = 0; float fraction_lost = 0.0f; int64_t rtt_ms = 0; diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc index 5240b2874b..234c7abc2d 100644 --- a/media/engine/webrtc_video_engine.cc +++ b/media/engine/webrtc_video_engine.cc @@ -2267,10 +2267,20 @@ VideoSenderInfo WebRtcVideoChannel::WebRtcVideoSendStream::GetVideoSenderInfo( it != stats.substreams.end(); ++it) { // TODO(pbos): Wire up additional stats, such as padding bytes. webrtc::VideoSendStream::StreamStats stream_stats = it->second; + // TODO(http://crbug.com/webrtc/10525): Bytes sent should only include + // payload bytes, not header and padding bytes. info.bytes_sent += stream_stats.rtp_stats.transmitted.payload_bytes + stream_stats.rtp_stats.transmitted.header_bytes + stream_stats.rtp_stats.transmitted.padding_bytes; info.packets_sent += stream_stats.rtp_stats.transmitted.packets; + // TODO(https://crbug.com/webrtc/10555): RTX retransmissions should show up + // in separate outbound-rtp stream objects. + if (!stream_stats.is_rtx && !stream_stats.is_flexfec) { + info.retransmitted_bytes_sent += + stream_stats.rtp_stats.retransmitted.payload_bytes; + info.retransmitted_packets_sent += + stream_stats.rtp_stats.retransmitted.packets; + } info.packets_lost += stream_stats.rtcp_stats.packets_lost; if (stream_stats.width > info.send_frame_width) info.send_frame_width = stream_stats.width; diff --git a/media/engine/webrtc_voice_engine.cc b/media/engine/webrtc_voice_engine.cc index 0765427e6f..9110d551e6 100644 --- a/media/engine/webrtc_voice_engine.cc +++ b/media/engine/webrtc_voice_engine.cc @@ -2192,7 +2192,9 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) { VoiceSenderInfo sinfo; sinfo.add_ssrc(stats.local_ssrc); sinfo.bytes_sent = stats.bytes_sent; + sinfo.retransmitted_bytes_sent = stats.retransmitted_bytes_sent; sinfo.packets_sent = stats.packets_sent; + sinfo.retransmitted_packets_sent = stats.retransmitted_packets_sent; sinfo.packets_lost = stats.packets_lost; sinfo.fraction_lost = stats.fraction_lost; sinfo.codec_name = stats.codec_name; diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc index f716718108..a15558d95a 100644 --- a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc +++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc @@ -542,6 +542,8 @@ int32_t ModuleRtpRtcpImpl::DataCountersRTP(size_t* bytes_sent, rtp_sender_->GetDataCounters(&rtp_stats, &rtx_stats); if (bytes_sent) { + // TODO(http://crbug.com/webrtc/10525): Bytes sent should only include + // payload bytes, not header and padding bytes. *bytes_sent = rtp_stats.transmitted.payload_bytes + rtp_stats.transmitted.padding_bytes + rtp_stats.transmitted.header_bytes + diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc index 3bf856636d..611dfe373e 100644 --- a/pc/rtc_stats_collector.cc +++ b/pc/rtc_stats_collector.cc @@ -295,8 +295,12 @@ void SetOutboundRTPStreamStatsFromMediaSenderInfo( outbound_stats->is_remote = false; outbound_stats->packets_sent = static_cast(media_sender_info.packets_sent); + outbound_stats->retransmitted_packets_sent = + media_sender_info.retransmitted_packets_sent; outbound_stats->bytes_sent = static_cast(media_sender_info.bytes_sent); + outbound_stats->retransmitted_bytes_sent = + media_sender_info.retransmitted_bytes_sent; } void SetOutboundRTPStreamStatsFromVoiceSenderInfo( diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc index 82cd241eed..ba80732ea2 100644 --- a/pc/rtc_stats_collector_unittest.cc +++ b/pc/rtc_stats_collector_unittest.cc @@ -1771,7 +1771,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) { voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo()); voice_media_info.senders[0].local_stats[0].ssrc = 1; voice_media_info.senders[0].packets_sent = 2; + voice_media_info.senders[0].retransmitted_packets_sent = 20; voice_media_info.senders[0].bytes_sent = 3; + voice_media_info.senders[0].retransmitted_bytes_sent = 30; voice_media_info.senders[0].codec_payload_type = 42; RtpCodecParameters codec_parameters; @@ -1799,7 +1801,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) { expected_audio.transport_id = "RTCTransport_TransportName_1"; expected_audio.codec_id = "RTCCodec_AudioMid_Outbound_42"; expected_audio.packets_sent = 2; + expected_audio.retransmitted_packets_sent = 20; expected_audio.bytes_sent = 3; + expected_audio.retransmitted_bytes_sent = 30; ASSERT_TRUE(report->Get(expected_audio.id())); EXPECT_EQ( @@ -1825,7 +1829,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) { video_media_info.senders[0].plis_rcvd = 3; video_media_info.senders[0].nacks_rcvd = 4; video_media_info.senders[0].packets_sent = 5; + video_media_info.senders[0].retransmitted_packets_sent = 50; video_media_info.senders[0].bytes_sent = 6; + video_media_info.senders[0].retransmitted_bytes_sent = 60; video_media_info.senders[0].codec_payload_type = 42; video_media_info.senders[0].frames_encoded = 8; video_media_info.senders[0].total_encode_time_ms = 9000; @@ -1865,7 +1871,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) { expected_video.pli_count = 3; expected_video.nack_count = 4; expected_video.packets_sent = 5; + expected_video.retransmitted_packets_sent = 50; expected_video.bytes_sent = 6; + expected_video.retransmitted_bytes_sent = 60; expected_video.frames_encoded = 8; expected_video.total_encode_time = 9.0; // |expected_video.content_type| should be undefined. @@ -2038,7 +2046,9 @@ TEST_F(RTCStatsCollectorTest, CollectNoStreamRTCOutboundRTPStreamStats_Audio) { voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo()); voice_media_info.senders[0].local_stats[0].ssrc = 1; voice_media_info.senders[0].packets_sent = 2; + voice_media_info.senders[0].retransmitted_packets_sent = 20; voice_media_info.senders[0].bytes_sent = 3; + voice_media_info.senders[0].retransmitted_bytes_sent = 30; voice_media_info.senders[0].codec_payload_type = 42; RtpCodecParameters codec_parameters; @@ -2067,7 +2077,9 @@ TEST_F(RTCStatsCollectorTest, CollectNoStreamRTCOutboundRTPStreamStats_Audio) { expected_audio.transport_id = "RTCTransport_TransportName_1"; expected_audio.codec_id = "RTCCodec_AudioMid_Outbound_42"; expected_audio.packets_sent = 2; + expected_audio.retransmitted_packets_sent = 20; expected_audio.bytes_sent = 3; + expected_audio.retransmitted_bytes_sent = 30; ASSERT_TRUE(report->Get(expected_audio.id())); EXPECT_EQ( diff --git a/pc/rtc_stats_integrationtest.cc b/pc/rtc_stats_integrationtest.cc index 9b1b6d02c2..bb13c20bf2 100644 --- a/pc/rtc_stats_integrationtest.cc +++ b/pc/rtc_stats_integrationtest.cc @@ -762,7 +762,11 @@ class RTCStatsReportVerifier { verifier.TestMemberIsUndefined(outbound_stream.qp_sum); } verifier.TestMemberIsNonNegative(outbound_stream.packets_sent); + verifier.TestMemberIsNonNegative( + outbound_stream.retransmitted_packets_sent); verifier.TestMemberIsNonNegative(outbound_stream.bytes_sent); + verifier.TestMemberIsNonNegative( + outbound_stream.retransmitted_bytes_sent); verifier.TestMemberIsUndefined(outbound_stream.target_bitrate); if (outbound_stream.media_type.is_defined() && *outbound_stream.media_type == "video") { diff --git a/stats/rtcstats_objects.cc b/stats/rtcstats_objects.cc index 4bf3e68346..89d5a85d7a 100644 --- a/stats/rtcstats_objects.cc +++ b/stats/rtcstats_objects.cc @@ -652,7 +652,9 @@ RTCInboundRTPStreamStats::~RTCInboundRTPStreamStats() {} WEBRTC_RTCSTATS_IMPL( RTCOutboundRTPStreamStats, RTCRTPStreamStats, "outbound-rtp", &packets_sent, + &retransmitted_packets_sent, &bytes_sent, + &retransmitted_bytes_sent, &target_bitrate, &frames_encoded, &total_encode_time, @@ -667,7 +669,9 @@ RTCOutboundRTPStreamStats::RTCOutboundRTPStreamStats(std::string&& id, int64_t timestamp_us) : RTCRTPStreamStats(std::move(id), timestamp_us), packets_sent("packetsSent"), + retransmitted_packets_sent("retransmittedPacketsSent"), bytes_sent("bytesSent"), + retransmitted_bytes_sent("retransmittedBytesSent"), target_bitrate("targetBitrate"), frames_encoded("framesEncoded"), total_encode_time("totalEncodeTime"), @@ -677,7 +681,9 @@ RTCOutboundRTPStreamStats::RTCOutboundRTPStreamStats( const RTCOutboundRTPStreamStats& other) : RTCRTPStreamStats(other), packets_sent(other.packets_sent), + retransmitted_packets_sent(other.retransmitted_packets_sent), bytes_sent(other.bytes_sent), + retransmitted_bytes_sent(other.retransmitted_bytes_sent), target_bitrate(other.target_bitrate), frames_encoded(other.frames_encoded), total_encode_time(other.total_encode_time),