Implement nack_count metric for outbound audio rtp streams.
Bug: webrtc:12510 Change-Id: Ia035885bced3c3d202bb9ffeb88c2556d4830e92 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/225021 Reviewed-by: Sam Zackrisson <saza@webrtc.org> Reviewed-by: Erik Språng <sprang@webrtc.org> Reviewed-by: Henrik Boström <hbos@webrtc.org> Commit-Queue: Jakob Ivarsson <jakobi@webrtc.org> Cr-Commit-Position: refs/heads/master@{#34444}
This commit is contained in:
parent
b629aee669
commit
e91c992fa1
@ -553,8 +553,6 @@ class RTC_EXPORT RTCOutboundRTPStreamStats final : public RTCRTPStreamStats {
|
||||
// FIR and PLI counts are only defined for |media_type == "video"|.
|
||||
RTCStatsMember<uint32_t> fir_count;
|
||||
RTCStatsMember<uint32_t> pli_count;
|
||||
// TODO(hbos): NACK count should be collected by |RTCStatsCollector| for both
|
||||
// audio and video but is only defined in the "video" case. crbug.com/657856
|
||||
RTCStatsMember<uint32_t> nack_count;
|
||||
RTCStatsMember<uint64_t> qp_sum;
|
||||
};
|
||||
|
||||
@ -498,6 +498,8 @@ webrtc::AudioSendStream::Stats AudioSendStream::GetStats(
|
||||
|
||||
stats.report_block_datas = std::move(call_stats.report_block_datas);
|
||||
|
||||
stats.nacks_rcvd = call_stats.nacks_rcvd;
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
|
||||
@ -60,8 +60,9 @@ class TransportSequenceNumberProxy;
|
||||
class VoERtcpObserver;
|
||||
|
||||
class ChannelSend : public ChannelSendInterface,
|
||||
public AudioPacketizationCallback { // receive encoded
|
||||
// packets from the ACM
|
||||
public AudioPacketizationCallback, // receive encoded
|
||||
// packets from the ACM
|
||||
public RtcpPacketTypeCounterObserver {
|
||||
public:
|
||||
// TODO(nisse): Make OnUplinkPacketLossRate public, and delete friend
|
||||
// declaration.
|
||||
@ -150,6 +151,11 @@ class ChannelSend : public ChannelSendInterface,
|
||||
rtc::scoped_refptr<webrtc::FrameTransformerInterface> frame_transformer)
|
||||
override;
|
||||
|
||||
// RtcpPacketTypeCounterObserver.
|
||||
void RtcpPacketTypesCounterUpdated(
|
||||
uint32_t ssrc,
|
||||
const RtcpPacketTypeCounter& packet_counter) override;
|
||||
|
||||
private:
|
||||
// From AudioPacketizationCallback in the ACM
|
||||
int32_t SendData(AudioFrameType frameType,
|
||||
@ -187,6 +193,7 @@ class ChannelSend : public ChannelSendInterface,
|
||||
|
||||
mutable Mutex volume_settings_mutex_;
|
||||
|
||||
const uint32_t ssrc_;
|
||||
bool sending_ RTC_GUARDED_BY(&worker_thread_checker_) = false;
|
||||
|
||||
RtcEventLog* const event_log_;
|
||||
@ -239,6 +246,10 @@ class ChannelSend : public ChannelSendInterface,
|
||||
rtc::TaskQueue encoder_queue_;
|
||||
|
||||
const bool fixing_timestamp_stall_;
|
||||
|
||||
mutable Mutex rtcp_counter_mutex_;
|
||||
RtcpPacketTypeCounter rtcp_packet_type_counter_
|
||||
RTC_GUARDED_BY(rtcp_counter_mutex_);
|
||||
};
|
||||
|
||||
const int kTelephoneEventAttenuationdB = 10;
|
||||
@ -452,7 +463,8 @@ ChannelSend::ChannelSend(
|
||||
uint32_t ssrc,
|
||||
rtc::scoped_refptr<FrameTransformerInterface> frame_transformer,
|
||||
TransportFeedbackObserver* feedback_observer)
|
||||
: event_log_(rtc_event_log),
|
||||
: ssrc_(ssrc),
|
||||
event_log_(rtc_event_log),
|
||||
_timeStamp(0), // This is just an offset, RTP module will add it's own
|
||||
// random offset
|
||||
input_mute_(false),
|
||||
@ -487,6 +499,7 @@ ChannelSend::ChannelSend(
|
||||
retransmission_rate_limiter_.get();
|
||||
configuration.extmap_allow_mixed = extmap_allow_mixed;
|
||||
configuration.rtcp_report_interval_ms = rtcp_report_interval_ms;
|
||||
configuration.rtcp_packet_type_counter_observer = this;
|
||||
|
||||
configuration.local_media_ssrc = ssrc;
|
||||
|
||||
@ -777,9 +790,24 @@ CallSendStatistics ChannelSend::GetRTCPStatistics() const {
|
||||
stats.retransmitted_packets_sent = rtp_stats.retransmitted.packets;
|
||||
stats.report_block_datas = rtp_rtcp_->GetLatestReportBlockData();
|
||||
|
||||
{
|
||||
MutexLock lock(&rtcp_counter_mutex_);
|
||||
stats.nacks_rcvd = rtcp_packet_type_counter_.nack_packets;
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
void ChannelSend::RtcpPacketTypesCounterUpdated(
|
||||
uint32_t ssrc,
|
||||
const RtcpPacketTypeCounter& packet_counter) {
|
||||
if (ssrc != ssrc_) {
|
||||
return;
|
||||
}
|
||||
MutexLock lock(&rtcp_counter_mutex_);
|
||||
rtcp_packet_type_counter_ = packet_counter;
|
||||
}
|
||||
|
||||
void ChannelSend::ProcessAndEncodeAudio(
|
||||
std::unique_ptr<AudioFrame> audio_frame) {
|
||||
RTC_DCHECK_RUNS_SERIALIZED(&audio_thread_race_checker_);
|
||||
|
||||
@ -45,6 +45,7 @@ struct CallSendStatistics {
|
||||
// ReportBlockData represents the latest Report Block that was received for
|
||||
// that pair.
|
||||
std::vector<ReportBlockData> report_block_datas;
|
||||
uint32_t nacks_rcvd;
|
||||
};
|
||||
|
||||
// See section 6.4.2 in http://www.ietf.org/rfc/rfc3550.txt for details.
|
||||
|
||||
@ -20,7 +20,7 @@ using NackTest = CallTest;
|
||||
TEST_F(NackTest, ShouldNackInLossyNetwork) {
|
||||
class NackTest : public AudioEndToEndTest {
|
||||
public:
|
||||
const int kTestDurationMs = 1000;
|
||||
const int kTestDurationMs = 2000;
|
||||
const int64_t kRttMs = 30;
|
||||
const int64_t kLossPercent = 30;
|
||||
const int kNackHistoryMs = 1000;
|
||||
@ -46,6 +46,9 @@ TEST_F(NackTest, ShouldNackInLossyNetwork) {
|
||||
AudioReceiveStream::Stats recv_stats =
|
||||
receive_stream()->GetStats(/*get_and_clear_legacy_stats=*/true);
|
||||
EXPECT_GT(recv_stats.nacks_sent, 0U);
|
||||
AudioSendStream::Stats send_stats = send_stream()->GetStats();
|
||||
EXPECT_GT(send_stats.retransmitted_packets_sent, 0U);
|
||||
EXPECT_GT(send_stats.nacks_rcvd, 0U);
|
||||
}
|
||||
} test;
|
||||
|
||||
|
||||
@ -70,6 +70,7 @@ class AudioSendStream : public AudioSender {
|
||||
// per-pair the ReportBlockData represents the latest Report Block that was
|
||||
// received for that pair.
|
||||
std::vector<ReportBlockData> report_block_datas;
|
||||
uint32_t nacks_rcvd = 0;
|
||||
};
|
||||
|
||||
struct Config {
|
||||
|
||||
@ -372,6 +372,8 @@ struct MediaSenderInfo {
|
||||
int packets_sent = 0;
|
||||
// https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-retransmittedpacketssent
|
||||
uint64_t retransmitted_packets_sent = 0;
|
||||
// https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-nackcount
|
||||
uint32_t nacks_rcvd = 0;
|
||||
int packets_lost = 0;
|
||||
float fraction_lost = 0.0f;
|
||||
int64_t rtt_ms = 0;
|
||||
@ -535,7 +537,6 @@ struct VideoSenderInfo : public MediaSenderInfo {
|
||||
std::string encoder_implementation_name;
|
||||
int firs_rcvd = 0;
|
||||
int plis_rcvd = 0;
|
||||
int nacks_rcvd = 0;
|
||||
int send_frame_width = 0;
|
||||
int send_frame_height = 0;
|
||||
int frames = 0;
|
||||
|
||||
@ -1894,7 +1894,7 @@ TEST_F(WebRtcVideoChannelBaseTest, GetStats) {
|
||||
EXPECT_EQ(DefaultCodec().id, *info.senders[0].codec_payload_type);
|
||||
EXPECT_EQ(0, info.senders[0].firs_rcvd);
|
||||
EXPECT_EQ(0, info.senders[0].plis_rcvd);
|
||||
EXPECT_EQ(0, info.senders[0].nacks_rcvd);
|
||||
EXPECT_EQ(0u, info.senders[0].nacks_rcvd);
|
||||
EXPECT_EQ(kVideoWidth, info.senders[0].send_frame_width);
|
||||
EXPECT_EQ(kVideoHeight, info.senders[0].send_frame_height);
|
||||
EXPECT_GT(info.senders[0].framerate_input, 0);
|
||||
@ -5555,7 +5555,7 @@ TEST_F(WebRtcVideoChannelTest, GetAggregatedStatsReportWithoutSubStreams) {
|
||||
// Comes from substream only.
|
||||
EXPECT_EQ(sender.firs_rcvd, 0);
|
||||
EXPECT_EQ(sender.plis_rcvd, 0);
|
||||
EXPECT_EQ(sender.nacks_rcvd, 0);
|
||||
EXPECT_EQ(sender.nacks_rcvd, 0u);
|
||||
EXPECT_EQ(sender.send_frame_width, 0);
|
||||
EXPECT_EQ(sender.send_frame_height, 0);
|
||||
|
||||
@ -5679,9 +5679,8 @@ TEST_F(WebRtcVideoChannelTest, GetAggregatedStatsReportForSubStreams) {
|
||||
EXPECT_EQ(
|
||||
sender.plis_rcvd,
|
||||
static_cast<int>(2 * substream.rtcp_packet_type_counts.pli_packets));
|
||||
EXPECT_EQ(
|
||||
sender.nacks_rcvd,
|
||||
static_cast<int>(2 * substream.rtcp_packet_type_counts.nack_packets));
|
||||
EXPECT_EQ(sender.nacks_rcvd,
|
||||
2 * substream.rtcp_packet_type_counts.nack_packets);
|
||||
EXPECT_EQ(sender.send_frame_width, substream.width);
|
||||
EXPECT_EQ(sender.send_frame_height, substream.height);
|
||||
|
||||
@ -5800,8 +5799,7 @@ TEST_F(WebRtcVideoChannelTest, GetPerLayerStatsReportForSubStreams) {
|
||||
static_cast<int>(substream.rtcp_packet_type_counts.fir_packets));
|
||||
EXPECT_EQ(sender.plis_rcvd,
|
||||
static_cast<int>(substream.rtcp_packet_type_counts.pli_packets));
|
||||
EXPECT_EQ(sender.nacks_rcvd,
|
||||
static_cast<int>(substream.rtcp_packet_type_counts.nack_packets));
|
||||
EXPECT_EQ(sender.nacks_rcvd, substream.rtcp_packet_type_counts.nack_packets);
|
||||
EXPECT_EQ(sender.send_frame_width, substream.width);
|
||||
EXPECT_EQ(sender.send_frame_height, substream.height);
|
||||
|
||||
@ -6122,15 +6120,15 @@ TEST_F(WebRtcVideoChannelTest, GetStatsTranslatesSendRtcpPacketTypesCorrectly) {
|
||||
cricket::VideoMediaInfo info;
|
||||
ASSERT_TRUE(channel_->GetStats(&info));
|
||||
EXPECT_EQ(2, info.senders[0].firs_rcvd);
|
||||
EXPECT_EQ(3, info.senders[0].nacks_rcvd);
|
||||
EXPECT_EQ(3u, info.senders[0].nacks_rcvd);
|
||||
EXPECT_EQ(4, info.senders[0].plis_rcvd);
|
||||
|
||||
EXPECT_EQ(5, info.senders[1].firs_rcvd);
|
||||
EXPECT_EQ(7, info.senders[1].nacks_rcvd);
|
||||
EXPECT_EQ(7u, info.senders[1].nacks_rcvd);
|
||||
EXPECT_EQ(9, info.senders[1].plis_rcvd);
|
||||
|
||||
EXPECT_EQ(7, info.aggregated_senders[0].firs_rcvd);
|
||||
EXPECT_EQ(10, info.aggregated_senders[0].nacks_rcvd);
|
||||
EXPECT_EQ(10u, info.aggregated_senders[0].nacks_rcvd);
|
||||
EXPECT_EQ(13, info.aggregated_senders[0].plis_rcvd);
|
||||
}
|
||||
|
||||
|
||||
@ -2320,6 +2320,7 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info,
|
||||
sinfo.retransmitted_packets_sent = stats.retransmitted_packets_sent;
|
||||
sinfo.packets_lost = stats.packets_lost;
|
||||
sinfo.fraction_lost = stats.fraction_lost;
|
||||
sinfo.nacks_rcvd = stats.nacks_rcvd;
|
||||
sinfo.codec_name = stats.codec_name;
|
||||
sinfo.codec_payload_type = stats.codec_payload_type;
|
||||
sinfo.jitter_ms = stats.jitter_ms;
|
||||
|
||||
@ -516,6 +516,7 @@ void SetOutboundRTPStreamStatsFromMediaSenderInfo(
|
||||
static_cast<uint64_t>(media_sender_info.header_and_padding_bytes_sent);
|
||||
outbound_stats->retransmitted_bytes_sent =
|
||||
media_sender_info.retransmitted_bytes_sent;
|
||||
outbound_stats->nack_count = media_sender_info.nacks_rcvd;
|
||||
}
|
||||
|
||||
void SetOutboundRTPStreamStatsFromVoiceSenderInfo(
|
||||
@ -550,8 +551,6 @@ void SetOutboundRTPStreamStatsFromVideoSenderInfo(
|
||||
static_cast<uint32_t>(video_sender_info.firs_rcvd);
|
||||
outbound_video->pli_count =
|
||||
static_cast<uint32_t>(video_sender_info.plis_rcvd);
|
||||
outbound_video->nack_count =
|
||||
static_cast<uint32_t>(video_sender_info.nacks_rcvd);
|
||||
if (video_sender_info.qp_sum)
|
||||
outbound_video->qp_sum = *video_sender_info.qp_sum;
|
||||
outbound_video->frames_encoded = video_sender_info.frames_encoded;
|
||||
|
||||
@ -2165,6 +2165,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) {
|
||||
voice_media_info.senders[0].payload_bytes_sent = 3;
|
||||
voice_media_info.senders[0].header_and_padding_bytes_sent = 12;
|
||||
voice_media_info.senders[0].retransmitted_bytes_sent = 30;
|
||||
voice_media_info.senders[0].nacks_rcvd = 31;
|
||||
voice_media_info.senders[0].codec_payload_type = 42;
|
||||
|
||||
RtpCodecParameters codec_parameters;
|
||||
@ -2198,6 +2199,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) {
|
||||
expected_audio.bytes_sent = 3;
|
||||
expected_audio.header_bytes_sent = 12;
|
||||
expected_audio.retransmitted_bytes_sent = 30;
|
||||
expected_audio.nack_count = 31;
|
||||
|
||||
ASSERT_TRUE(report->Get(expected_audio.id()));
|
||||
EXPECT_EQ(
|
||||
@ -2562,6 +2564,7 @@ TEST_F(RTCStatsCollectorTest, CollectNoStreamRTCOutboundRTPStreamStats_Audio) {
|
||||
voice_media_info.senders[0].payload_bytes_sent = 3;
|
||||
voice_media_info.senders[0].header_and_padding_bytes_sent = 4;
|
||||
voice_media_info.senders[0].retransmitted_bytes_sent = 30;
|
||||
voice_media_info.senders[0].nacks_rcvd = 31;
|
||||
voice_media_info.senders[0].codec_payload_type = 42;
|
||||
|
||||
RtpCodecParameters codec_parameters;
|
||||
@ -2595,6 +2598,7 @@ TEST_F(RTCStatsCollectorTest, CollectNoStreamRTCOutboundRTPStreamStats_Audio) {
|
||||
expected_audio.bytes_sent = 3;
|
||||
expected_audio.header_bytes_sent = 4;
|
||||
expected_audio.retransmitted_bytes_sent = 30;
|
||||
expected_audio.nack_count = 31;
|
||||
|
||||
ASSERT_TRUE(report->Get(expected_audio.id()));
|
||||
EXPECT_EQ(
|
||||
|
||||
@ -934,7 +934,6 @@ class RTCStatsReportVerifier {
|
||||
RTCVideoSourceStats::kType);
|
||||
verifier.TestMemberIsNonNegative<uint32_t>(outbound_stream.fir_count);
|
||||
verifier.TestMemberIsNonNegative<uint32_t>(outbound_stream.pli_count);
|
||||
verifier.TestMemberIsNonNegative<uint32_t>(outbound_stream.nack_count);
|
||||
if (*outbound_stream.frames_encoded > 0) {
|
||||
verifier.TestMemberIsNonNegative<uint64_t>(outbound_stream.qp_sum);
|
||||
} else {
|
||||
@ -943,11 +942,11 @@ class RTCStatsReportVerifier {
|
||||
} else {
|
||||
verifier.TestMemberIsUndefined(outbound_stream.fir_count);
|
||||
verifier.TestMemberIsUndefined(outbound_stream.pli_count);
|
||||
verifier.TestMemberIsUndefined(outbound_stream.nack_count);
|
||||
verifier.TestMemberIsIDReference(outbound_stream.media_source_id,
|
||||
RTCAudioSourceStats::kType);
|
||||
verifier.TestMemberIsUndefined(outbound_stream.qp_sum);
|
||||
}
|
||||
verifier.TestMemberIsNonNegative<uint32_t>(outbound_stream.nack_count);
|
||||
verifier.TestMemberIsOptionalIDReference(
|
||||
outbound_stream.remote_id, RTCRemoteInboundRtpStreamStats::kType);
|
||||
verifier.TestMemberIsNonNegative<uint32_t>(outbound_stream.packets_sent);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user