stats: implement flexfec fecBytesReceived stats for FlexFEC

specified in https://github.com/w3c/webrtc-stats/pull/762
and take FlexFEC into account for receive statistics.

BUG=webrtc:15250

Change-Id: Id85775ab1f29487d5b8bf478da6e22071005901a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/294881
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Commit-Queue: Philipp Hancke <phancke@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#40325}
This commit is contained in:
Philipp Hancke 2023-06-21 13:53:41 +02:00 committed by WebRTC LUCI CQ
parent d7c7b07c5d
commit 17e8a5cc7d
13 changed files with 65 additions and 7 deletions

View file

@ -248,6 +248,7 @@ class RTC_EXPORT RTCInboundRtpStreamStats final
RTCStatsMember<uint32_t> packets_received;
RTCStatsMember<uint64_t> packets_discarded;
RTCStatsMember<uint64_t> fec_packets_received;
RTCStatsMember<uint64_t> fec_bytes_received;
RTCStatsMember<uint64_t> fec_packets_discarded;
RTCStatsMember<uint64_t> bytes_received;
RTCStatsMember<uint64_t> header_bytes_received;

View file

@ -67,6 +67,7 @@ rtc_library("call_interfaces") {
"../modules/audio_processing",
"../modules/audio_processing:api",
"../modules/audio_processing:audio_processing_statistics",
"../modules/rtp_rtcp",
"../modules/rtp_rtcp:rtp_rtcp_format",
"../rtc_base:audio_format_to_string",
"../rtc_base:checks",

View file

@ -21,6 +21,7 @@
#include "api/rtp_parameters.h"
#include "call/receive_stream.h"
#include "call/rtp_packet_sink_interface.h"
#include "modules/rtp_rtcp/include/receive_statistics.h"
namespace webrtc {
@ -69,6 +70,8 @@ class FlexfecReceiveStream : public RtpPacketSinkInterface,
// Called to change the payload type after initialization.
virtual void SetPayloadType(int payload_type) = 0;
virtual int payload_type() const = 0;
virtual const ReceiveStatistics* GetStats() const = 0;
};
} // namespace webrtc

View file

@ -21,7 +21,6 @@
#include "api/rtp_parameters.h"
#include "call/rtp_stream_receiver_controller_interface.h"
#include "modules/rtp_rtcp/include/flexfec_receiver.h"
#include "modules/rtp_rtcp/include/receive_statistics.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"

View file

@ -70,6 +70,10 @@ class FlexfecReceiveStreamImpl : public FlexfecReceiveStream {
rtp_rtcp_->SetRTCPStatus(mode);
}
const ReceiveStatistics* GetStats() const override {
return rtp_receive_statistics_.get();
}
private:
RTC_NO_UNIQUE_ADDRESS SequenceChecker packet_sequence_checker_;

View file

@ -538,6 +538,7 @@ rtc_library("rtc_audio_video") {
"../modules/audio_processing:audio_processing_statistics",
"../modules/audio_processing/aec_dump",
"../modules/audio_processing/agc:gain_control_interface",
"../modules/rtp_rtcp",
"../modules/rtp_rtcp:rtp_rtcp_format",
"../modules/video_coding",
"../modules/video_coding:video_codec_interface",

View file

@ -462,6 +462,12 @@ struct MediaReceiverInfo {
absl::optional<int> codec_payload_type;
std::vector<SsrcReceiverInfo> local_stats;
std::vector<SsrcSenderInfo> remote_stats;
// https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats-fecpacketsreceived
absl::optional<uint64_t> fec_packets_received;
// https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats-fecpacketsdiscarded
absl::optional<uint64_t> fec_packets_discarded;
// https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats-fecbytesreceived
absl::optional<uint64_t> fec_bytes_received;
};
struct VoiceSenderInfo : public MediaSenderInfo {
@ -496,8 +502,6 @@ struct VoiceReceiverInfo : public MediaReceiverInfo {
uint64_t concealment_events = 0;
uint64_t inserted_samples_for_deceleration = 0;
uint64_t removed_samples_for_acceleration = 0;
uint64_t fec_packets_received = 0;
uint64_t fec_packets_discarded = 0;
// Stats below correspond to similarly-named fields in the WebRTC stats spec.
// https://w3c.github.io/webrtc-stats/#dom-rtcreceivedrtpstreamstats
uint64_t packets_discarded = 0;

View file

@ -348,6 +348,8 @@ class FakeFlexfecReceiveStream final : public webrtc::FlexfecReceiveStream {
uint32_t remote_ssrc() const { return config_.rtp.remote_ssrc; }
const webrtc::ReceiveStatistics* GetStats() const override { return nullptr; }
private:
void OnRtpPacket(const webrtc::RtpPacketReceived& packet) override;

View file

@ -51,6 +51,7 @@
#include "media/base/rid_description.h"
#include "media/base/rtp_utils.h"
#include "media/engine/webrtc_media_engine.h"
#include "modules/rtp_rtcp/include/receive_statistics.h"
#include "modules/rtp_rtcp/include/report_block_data.h"
#include "modules/rtp_rtcp/include/rtcp_statistics.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
@ -3652,6 +3653,29 @@ WebRtcVideoReceiveChannel::WebRtcVideoReceiveStream::GetVideoReceiverInfo(
info.packets_received += stats.rtx_rtp_stats->packet_counter.packets;
}
if (flexfec_stream_) {
const webrtc::ReceiveStatistics* fec_stats = flexfec_stream_->GetStats();
if (fec_stats) {
const webrtc::StreamStatistician* statistican =
fec_stats->GetStatistician(flexfec_config_.rtp.remote_ssrc);
if (statistican) {
const webrtc::RtpReceiveStats fec_rtp_stats = statistican->GetStats();
info.fec_packets_received = fec_rtp_stats.packet_counter.packets;
// TODO(bugs.webrtc.org/15250): implement fecPacketsDiscarded.
info.fec_bytes_received = fec_rtp_stats.packet_counter.payload_bytes;
// FEC information gets added to primary counters.
info.payload_bytes_received +=
fec_rtp_stats.packet_counter.payload_bytes;
info.header_and_padding_bytes_received +=
fec_rtp_stats.packet_counter.header_bytes +
fec_rtp_stats.packet_counter.padding_bytes;
info.packets_received += fec_rtp_stats.packet_counter.packets;
} else {
info.fec_packets_received = 0;
}
}
}
if (log_stats)
RTC_LOG(LS_INFO) << stats.ToString(rtc::TimeMillis());

View file

@ -425,6 +425,17 @@ void SetInboundRTPStreamStatsFromMediaReceiverInfo(
if (media_receiver_info.nacks_sent.has_value()) {
inbound_stats->nack_count = *media_receiver_info.nacks_sent;
}
if (media_receiver_info.fec_packets_received.has_value()) {
inbound_stats->fec_packets_received =
*media_receiver_info.fec_packets_received;
}
if (media_receiver_info.fec_packets_discarded.has_value()) {
inbound_stats->fec_packets_discarded =
*media_receiver_info.fec_packets_discarded;
}
if (media_receiver_info.fec_bytes_received.has_value()) {
inbound_stats->fec_bytes_received = *media_receiver_info.fec_bytes_received;
}
}
std::unique_ptr<RTCInboundRtpStreamStats> CreateInboundAudioStreamStats(
@ -483,10 +494,6 @@ std::unique_ptr<RTCInboundRtpStreamStats> CreateInboundAudioStreamStats(
inbound_audio->estimated_playout_timestamp = static_cast<double>(
*voice_receiver_info.estimated_playout_ntp_timestamp_ms);
}
inbound_audio->fec_packets_received =
voice_receiver_info.fec_packets_received;
inbound_audio->fec_packets_discarded =
voice_receiver_info.fec_packets_discarded;
inbound_audio->packets_discarded = voice_receiver_info.packets_discarded;
inbound_audio->jitter_buffer_flushes =
voice_receiver_info.jitter_buffer_flushes;
@ -670,6 +677,7 @@ CreateInboundRTPStreamStatsFromVideoReceiverInfo(
inbound_video->power_efficient_decoder =
*video_receiver_info.power_efficient_decoder;
}
return inbound_video;
}

View file

@ -2348,6 +2348,8 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRtpStreamStats_Video) {
video_media_info.receivers[0].power_efficient_decoder = false;
video_media_info.receivers[0].retransmitted_packets_received = 17;
video_media_info.receivers[0].retransmitted_bytes_received = 62;
video_media_info.receivers[0].fec_packets_received = 32;
video_media_info.receivers[0].fec_bytes_received = 54;
// Note: these two values intentionally differ,
// only the decoded one should show up.
@ -2412,6 +2414,8 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRtpStreamStats_Video) {
expected_video.power_efficient_decoder = false;
expected_video.retransmitted_packets_received = 17;
expected_video.retransmitted_bytes_received = 62;
expected_video.fec_packets_received = 32;
expected_video.fec_bytes_received = 54;
ASSERT_TRUE(report->Get(expected_video.id()));
EXPECT_EQ(

View file

@ -608,8 +608,13 @@ class RTCStatsReportVerifier {
inbound_stream.fec_packets_received);
verifier.TestMemberIsNonNegative<uint64_t>(
inbound_stream.fec_packets_discarded);
verifier.TestMemberIsUndefined(inbound_stream.fec_bytes_received);
} else {
verifier.TestMemberIsUndefined(inbound_stream.packets_discarded);
// FEC stats are only present when FlexFEC was negotiated which is guarded
// by the WebRTC-FlexFEC-03-Advertised/Enabled/ field trial and off by
// default.
verifier.TestMemberIsUndefined(inbound_stream.fec_bytes_received);
verifier.TestMemberIsUndefined(inbound_stream.fec_packets_received);
verifier.TestMemberIsUndefined(inbound_stream.fec_packets_discarded);
}

View file

@ -307,6 +307,7 @@ WEBRTC_RTCSTATS_IMPL(
&packets_received,
&packets_discarded,
&fec_packets_received,
&fec_bytes_received,
&fec_packets_discarded,
&bytes_received,
&header_bytes_received,
@ -371,6 +372,7 @@ RTCInboundRtpStreamStats::RTCInboundRtpStreamStats(std::string id,
packets_received("packetsReceived"),
packets_discarded("packetsDiscarded"),
fec_packets_received("fecPacketsReceived"),
fec_bytes_received("fecBytesReceived"),
fec_packets_discarded("fecPacketsDiscarded"),
bytes_received("bytesReceived"),
header_bytes_received("headerBytesReceived"),