diff --git a/api/stats/rtcstats_objects.h b/api/stats/rtcstats_objects.h index 7742538ca7..3795d79f5e 100644 --- a/api/stats/rtcstats_objects.h +++ b/api/stats/rtcstats_objects.h @@ -529,7 +529,7 @@ class RTC_EXPORT RTCOutboundRTPStreamStats final : public RTCRTPStreamStats { RTCStatsMember bytes_sent; RTCStatsMember header_bytes_sent; RTCStatsMember retransmitted_bytes_sent; - // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7066 + // TODO(https://crbug.com/webrtc/13394): Also collect this metric for video. RTCStatsMember target_bitrate; RTCStatsMember frames_encoded; RTCStatsMember key_frames_encoded; diff --git a/audio/audio_send_stream.cc b/audio/audio_send_stream.cc index 7d70592f76..08bb4e6bbf 100644 --- a/audio/audio_send_stream.cc +++ b/audio/audio_send_stream.cc @@ -427,7 +427,7 @@ webrtc::AudioSendStream::Stats AudioSendStream::GetStats( RTC_DCHECK_RUN_ON(&worker_thread_checker_); webrtc::AudioSendStream::Stats stats; stats.local_ssrc = config_.rtp.ssrc; - stats.target_bitrate_bps = channel_send_->GetBitrate(); + stats.target_bitrate_bps = channel_send_->GetTargetBitrate(); webrtc::CallSendStatistics call_stats = channel_send_->GetRTCPStatistics(); stats.payload_bytes_sent = call_stats.payload_bytes_sent; diff --git a/audio/audio_send_stream_unittest.cc b/audio/audio_send_stream_unittest.cc index 3c5b1423b2..9228611e31 100644 --- a/audio/audio_send_stream_unittest.cc +++ b/audio/audio_send_stream_unittest.cc @@ -300,7 +300,7 @@ struct ConfigHelper { .WillRepeatedly(Return(report_blocks)); EXPECT_CALL(*channel_send_, GetANAStatistics()) .WillRepeatedly(Return(ANAStats())); - EXPECT_CALL(*channel_send_, GetBitrate()).WillRepeatedly(Return(0)); + EXPECT_CALL(*channel_send_, GetTargetBitrate()).WillRepeatedly(Return(0)); audio_processing_stats_.echo_return_loss = kEchoReturnLoss; audio_processing_stats_.echo_return_loss_enhancement = diff --git a/audio/channel_send.cc b/audio/channel_send.cc index 6a65655d70..2ad031e543 100644 --- a/audio/channel_send.cc +++ b/audio/channel_send.cc @@ -96,7 +96,7 @@ class ChannelSend : public ChannelSendInterface, // Codecs void OnBitrateAllocation(BitrateAllocationUpdate update) override; - int GetBitrate() const override; + int GetTargetBitrate() const override; // Network void ReceivedRTCPPacket(const uint8_t* data, size_t length) override; @@ -238,9 +238,6 @@ class ChannelSend : public ChannelSendInterface, rtc::scoped_refptr frame_transformer_delegate_ RTC_GUARDED_BY(encoder_queue_); - mutable Mutex bitrate_mutex_; - int configured_bitrate_bps_ RTC_GUARDED_BY(bitrate_mutex_) = 0; - // Defined last to ensure that there are no running tasks when the other // members are destroyed. rtc::TaskQueue encoder_queue_; @@ -616,18 +613,14 @@ void ChannelSend::OnBitrateAllocation(BitrateAllocationUpdate update) { // rules. // RTC_DCHECK(worker_thread_checker_.IsCurrent() || // module_process_thread_checker_.IsCurrent()); - MutexLock lock(&bitrate_mutex_); - CallEncoder([&](AudioEncoder* encoder) { encoder->OnReceivedUplinkAllocation(update); }); retransmission_rate_limiter_->SetMaxRate(update.target_bitrate.bps()); - configured_bitrate_bps_ = update.target_bitrate.bps(); } -int ChannelSend::GetBitrate() const { - MutexLock lock(&bitrate_mutex_); - return configured_bitrate_bps_; +int ChannelSend::GetTargetBitrate() const { + return audio_coding_->GetTargetBitrate(); } void ChannelSend::OnUplinkPacketLossRate(float packet_loss_rate) { diff --git a/audio/channel_send.h b/audio/channel_send.h index 663b947036..e100725460 100644 --- a/audio/channel_send.h +++ b/audio/channel_send.h @@ -91,7 +91,7 @@ class ChannelSendInterface { int payload_frequency) = 0; virtual bool SendTelephoneEventOutband(int event, int duration_ms) = 0; virtual void OnBitrateAllocation(BitrateAllocationUpdate update) = 0; - virtual int GetBitrate() const = 0; + virtual int GetTargetBitrate() const = 0; virtual void SetInputMute(bool muted) = 0; virtual void ProcessAndEncodeAudio( diff --git a/audio/mock_voe_channel_proxy.h b/audio/mock_voe_channel_proxy.h index d445b51312..a02bee38ad 100644 --- a/audio/mock_voe_channel_proxy.h +++ b/audio/mock_voe_channel_proxy.h @@ -166,7 +166,7 @@ class MockChannelSend : public voe::ChannelSendInterface { (std::unique_ptr), (override)); MOCK_METHOD(RtpRtcpInterface*, GetRtpRtcp, (), (const, override)); - MOCK_METHOD(int, GetBitrate, (), (const, override)); + MOCK_METHOD(int, GetTargetBitrate, (), (const, override)); MOCK_METHOD(int64_t, GetRTT, (), (const, override)); MOCK_METHOD(void, StartSend, (), (override)); MOCK_METHOD(void, StopSend, (), (override)); diff --git a/media/base/media_channel.h b/media/base/media_channel.h index 2607a7a4aa..519ca5dd6d 100644 --- a/media/base/media_channel.h +++ b/media/base/media_channel.h @@ -375,6 +375,8 @@ struct MediaSenderInfo { uint64_t retransmitted_packets_sent = 0; // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-nackcount uint32_t nacks_rcvd = 0; + // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-targetbitrate + double target_bitrate = 0.0; int packets_lost = 0; float fraction_lost = 0.0f; int64_t rtt_ms = 0; diff --git a/media/engine/webrtc_voice_engine.cc b/media/engine/webrtc_voice_engine.cc index 5d4455c2de..6934a0ca54 100644 --- a/media/engine/webrtc_voice_engine.cc +++ b/media/engine/webrtc_voice_engine.cc @@ -2369,6 +2369,7 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info, sinfo.packets_lost = stats.packets_lost; sinfo.fraction_lost = stats.fraction_lost; sinfo.nacks_rcvd = stats.nacks_rcvd; + sinfo.target_bitrate = stats.target_bitrate_bps; sinfo.codec_name = stats.codec_name; sinfo.codec_payload_type = stats.codec_payload_type; sinfo.jitter_ms = stats.jitter_ms; diff --git a/modules/audio_coding/acm2/audio_coding_module.cc b/modules/audio_coding/acm2/audio_coding_module.cc index 8ba1b9f3de..b742a824a9 100644 --- a/modules/audio_coding/acm2/audio_coding_module.cc +++ b/modules/audio_coding/acm2/audio_coding_module.cc @@ -92,6 +92,8 @@ class AudioCodingModuleImpl final : public AudioCodingModule { ANAStats GetANAStats() const override; + int GetTargetBitrate() const override; + private: struct InputData { InputData() : buffer(kInitialInputDataBufferSize) {} @@ -603,6 +605,14 @@ ANAStats AudioCodingModuleImpl::GetANAStats() const { return ANAStats(); } +int AudioCodingModuleImpl::GetTargetBitrate() const { + MutexLock lock(&acm_mutex_); + if (!encoder_stack_) { + return -1; + } + return encoder_stack_->GetTargetBitrate(); +} + } // namespace AudioCodingModule::Config::Config( diff --git a/modules/audio_coding/include/audio_coding_module.h b/modules/audio_coding/include/audio_coding_module.h index 7551814023..9b1dce8e74 100644 --- a/modules/audio_coding/include/audio_coding_module.h +++ b/modules/audio_coding/include/audio_coding_module.h @@ -237,6 +237,8 @@ class AudioCodingModule { NetworkStatistics* network_statistics) = 0; virtual ANAStats GetANAStats() const = 0; + + virtual int GetTargetBitrate() const = 0; }; } // namespace webrtc diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc index 7637c07c09..23e24dc849 100644 --- a/pc/rtc_stats_collector.cc +++ b/pc/rtc_stats_collector.cc @@ -536,6 +536,9 @@ void SetOutboundRTPStreamStatsFromVoiceSenderInfo( outbound_audio); outbound_audio->media_type = "audio"; outbound_audio->kind = "audio"; + if (voice_sender_info.target_bitrate > 0) { + outbound_audio->target_bitrate = voice_sender_info.target_bitrate; + } if (voice_sender_info.codec_payload_type) { outbound_audio->codec_id = RTCCodecStatsIDFromMidDirectionAndPayload( mid, /*inbound=*/false, *voice_sender_info.codec_payload_type); diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc index b8c321394b..8c3c42f8ad 100644 --- a/pc/rtc_stats_collector_unittest.cc +++ b/pc/rtc_stats_collector_unittest.cc @@ -2180,6 +2180,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) { 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].target_bitrate = 32000; voice_media_info.senders[0].codec_payload_type = 42; RtpCodecParameters codec_parameters; @@ -2214,6 +2215,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) { expected_audio.header_bytes_sent = 12; expected_audio.retransmitted_bytes_sent = 30; expected_audio.nack_count = 31; + expected_audio.target_bitrate = 32000; ASSERT_TRUE(report->Get(expected_audio.id())); EXPECT_EQ( diff --git a/pc/rtc_stats_integrationtest.cc b/pc/rtc_stats_integrationtest.cc index 81ead00efe..32c567ee45 100644 --- a/pc/rtc_stats_integrationtest.cc +++ b/pc/rtc_stats_integrationtest.cc @@ -964,7 +964,6 @@ class RTCStatsReportVerifier { outbound_stream.header_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") { verifier.TestMemberIsDefined(outbound_stream.frames_encoded); @@ -1000,6 +999,7 @@ class RTCStatsReportVerifier { verifier.TestMemberIsNonNegative(outbound_stream.frames_sent); verifier.TestMemberIsNonNegative( outbound_stream.huge_frames_sent); + verifier.TestMemberIsUndefined(outbound_stream.target_bitrate); verifier.MarkMemberTested(outbound_stream.rid, true); } else { verifier.TestMemberIsUndefined(outbound_stream.frames_encoded); @@ -1023,6 +1023,7 @@ class RTCStatsReportVerifier { verifier.TestMemberIsUndefined(outbound_stream.frame_width); verifier.TestMemberIsUndefined(outbound_stream.frames_sent); verifier.TestMemberIsUndefined(outbound_stream.huge_frames_sent); + verifier.TestMemberIsNonNegative(outbound_stream.target_bitrate); } return verifier.ExpectAllMembersSuccessfullyTested(); }