diff --git a/api/stats/rtcstats_objects.h b/api/stats/rtcstats_objects.h index d0a62079eb..2554ea07de 100644 --- a/api/stats/rtcstats_objects.h +++ b/api/stats/rtcstats_objects.h @@ -545,6 +545,7 @@ class RTC_EXPORT RTCOutboundRTPStreamStats final : public RTCRTPStreamStats { RTCStatsMember pli_count; RTCStatsMember nack_count; RTCStatsMember qp_sum; + RTCStatsMember active; }; // https://w3c.github.io/webrtc-stats/#remoteinboundrtpstats-dict* diff --git a/media/base/media_channel.h b/media/base/media_channel.h index 712b63486c..6c80d6d37b 100644 --- a/media/base/media_channel.h +++ b/media/base/media_channel.h @@ -404,6 +404,7 @@ struct MediaSenderInfo { // this list, the ReportBlockData::RTCPReportBlock::source_ssrc(), which is // the SSRC of the corresponding outbound RTP stream, is unique. std::vector report_block_datas; + absl::optional active; }; struct MediaReceiverInfo { diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc index 366a42c894..89bf1f57ad 100644 --- a/media/engine/webrtc_video_engine.cc +++ b/media/engine/webrtc_video_engine.cc @@ -2666,6 +2666,15 @@ WebRtcVideoChannel::WebRtcVideoSendStream::GetPerLayerVideoSenderInfos( auto info = common_info; info.add_ssrc(pair.first); info.rid = parameters_.config.rtp.GetRidForSsrc(pair.first); + // Search the associated encoding by SSRC. + auto encoding_it = std::find_if( + rtp_parameters_.encodings.begin(), rtp_parameters_.encodings.end(), + [&pair](const webrtc::RtpEncodingParameters& parameters) { + return parameters.ssrc && pair.first == *parameters.ssrc; + }); + if (encoding_it != rtp_parameters_.encodings.end()) { + info.active = encoding_it->active; + } auto stream_stats = pair.second; RTC_DCHECK_EQ(stream_stats.type, webrtc::VideoSendStream::StreamStats::StreamType::kMedia); diff --git a/media/engine/webrtc_voice_engine.cc b/media/engine/webrtc_voice_engine.cc index b34c77d5b0..831e1f5deb 100644 --- a/media/engine/webrtc_voice_engine.cc +++ b/media/engine/webrtc_voice_engine.cc @@ -2317,6 +2317,12 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info, sinfo.ana_statistics = stats.ana_statistics; sinfo.apm_statistics = stats.apm_statistics; sinfo.report_block_datas = std::move(stats.report_block_datas); + + auto encodings = stream.second->rtp_parameters().encodings; + if (!encodings.empty()) { + sinfo.active = encodings[0].active; + } + info->senders.push_back(sinfo); } diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc index deb7e18449..e9bc83d1f4 100644 --- a/pc/rtc_stats_collector.cc +++ b/pc/rtc_stats_collector.cc @@ -600,7 +600,8 @@ void SetInboundRTPStreamStatsFromVideoReceiverInfo( } } -// Provides the media independent counters (both audio and video). +// Provides the media independent counters and information (both audio and +// video). void SetOutboundRTPStreamStatsFromMediaSenderInfo( const cricket::MediaSenderInfo& media_sender_info, RTCOutboundRTPStreamStats* outbound_stats) { @@ -617,6 +618,10 @@ void SetOutboundRTPStreamStatsFromMediaSenderInfo( outbound_stats->retransmitted_bytes_sent = media_sender_info.retransmitted_bytes_sent; outbound_stats->nack_count = media_sender_info.nacks_rcvd; + + if (media_sender_info.active.has_value()) { + outbound_stats->active = *media_sender_info.active; + } } void SetOutboundRTPStreamStatsFromVoiceSenderInfo( diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc index 2fff71a1ed..d3c4584555 100644 --- a/pc/rtc_stats_collector_unittest.cc +++ b/pc/rtc_stats_collector_unittest.cc @@ -2295,6 +2295,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) { voice_media_info.senders[0].nacks_rcvd = 31; voice_media_info.senders[0].target_bitrate = 32000; voice_media_info.senders[0].codec_payload_type = 42; + voice_media_info.senders[0].active = true; RtpCodecParameters codec_parameters; codec_parameters.payload_type = 42; @@ -2329,6 +2330,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) { expected_audio.retransmitted_bytes_sent = 30; expected_audio.nack_count = 31; expected_audio.target_bitrate = 32000; + expected_audio.active = true; ASSERT_TRUE(report->Get(expected_audio.id())); EXPECT_EQ( @@ -2377,6 +2379,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) { video_media_info.senders[0].framerate_sent = 10; video_media_info.senders[0].frames_sent = 5; video_media_info.senders[0].huge_frames_sent = 2; + video_media_info.senders[0].active = false; video_media_info.aggregated_senders.push_back(video_media_info.senders[0]); RtpCodecParameters codec_parameters; codec_parameters.payload_type = 42; @@ -2433,6 +2436,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) { expected_video.frames_per_second = 10.0; expected_video.frames_sent = 5; expected_video.huge_frames_sent = 2; + expected_video.active = false; // `expected_video.content_type` should be undefined. // `expected_video.qp_sum` should be undefined. // `expected_video.encoder_implementation` should be undefined. @@ -2725,6 +2729,7 @@ TEST_F(RTCStatsCollectorTest, CollectNoStreamRTCOutboundRTPStreamStats_Audio) { 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; + voice_media_info.senders[0].active = true; RtpCodecParameters codec_parameters; codec_parameters.payload_type = 42; @@ -2758,6 +2763,7 @@ TEST_F(RTCStatsCollectorTest, CollectNoStreamRTCOutboundRTPStreamStats_Audio) { expected_audio.header_bytes_sent = 4; expected_audio.retransmitted_bytes_sent = 30; expected_audio.nack_count = 31; + expected_audio.active = true; ASSERT_TRUE(report->Get(expected_audio.id())); EXPECT_EQ( diff --git a/pc/rtc_stats_integrationtest.cc b/pc/rtc_stats_integrationtest.cc index 4cb9c15a6f..057bf0f1c1 100644 --- a/pc/rtc_stats_integrationtest.cc +++ b/pc/rtc_stats_integrationtest.cc @@ -927,6 +927,7 @@ class RTCStatsReportVerifier { RTCStatsVerifier verifier(report_.get(), &outbound_stream); VerifyRTCRTPStreamStats(outbound_stream, verifier); verifier.TestMemberIsDefined(outbound_stream.mid); + verifier.TestMemberIsDefined(outbound_stream.active); if (outbound_stream.kind.is_defined() && *outbound_stream.kind == "video") { verifier.TestMemberIsIDReference(outbound_stream.media_source_id, RTCVideoSourceStats::kType); diff --git a/stats/rtcstats_objects.cc b/stats/rtcstats_objects.cc index d05c566e7b..321d8db86f 100644 --- a/stats/rtcstats_objects.cc +++ b/stats/rtcstats_objects.cc @@ -816,7 +816,8 @@ WEBRTC_RTCSTATS_IMPL( &fir_count, &pli_count, &nack_count, - &qp_sum) + &qp_sum, + &active) // clang-format on RTCOutboundRTPStreamStats::RTCOutboundRTPStreamStats(const std::string& id, @@ -855,7 +856,8 @@ RTCOutboundRTPStreamStats::RTCOutboundRTPStreamStats(std::string&& id, fir_count("firCount"), pli_count("pliCount"), nack_count("nackCount"), - qp_sum("qpSum") {} + qp_sum("qpSum"), + active("active") {} RTCOutboundRTPStreamStats::RTCOutboundRTPStreamStats( const RTCOutboundRTPStreamStats& other) @@ -889,7 +891,8 @@ RTCOutboundRTPStreamStats::RTCOutboundRTPStreamStats( fir_count(other.fir_count), pli_count(other.pli_count), nack_count(other.nack_count), - qp_sum(other.qp_sum) {} + qp_sum(other.qp_sum), + active(other.active) {} RTCOutboundRTPStreamStats::~RTCOutboundRTPStreamStats() {}