Implement RTCOutboundRtpStreamStats.targetBitrate for audio.

Spec: https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-targetbitrate

Bug: webrtc:13377
Change-Id: I98dd263e0b9d6e2ca94969d2a91857b14cd65f70
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/237402
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Minyue Li <minyue@webrtc.org>
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Commit-Queue: Jakob Ivarsson <jakobi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#35337}
This commit is contained in:
Jakob Ivarsson
2021-11-11 13:43:49 +01:00
committed by WebRTC LUCI CQ
parent 1d73243466
commit bf0874568c
13 changed files with 30 additions and 16 deletions

View File

@ -529,7 +529,7 @@ class RTC_EXPORT RTCOutboundRTPStreamStats final : public RTCRTPStreamStats {
RTCStatsMember<uint64_t> bytes_sent;
RTCStatsMember<uint64_t> header_bytes_sent;
RTCStatsMember<uint64_t> 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<double> target_bitrate;
RTCStatsMember<uint32_t> frames_encoded;
RTCStatsMember<uint32_t> key_frames_encoded;

View File

@ -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;

View File

@ -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 =

View File

@ -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<ChannelSendFrameTransformerDelegate>
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) {

View File

@ -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(

View File

@ -166,7 +166,7 @@ class MockChannelSend : public voe::ChannelSendInterface {
(std::unique_ptr<AudioFrame>),
(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));

View File

@ -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;

View File

@ -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;

View File

@ -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(

View File

@ -237,6 +237,8 @@ class AudioCodingModule {
NetworkStatistics* network_statistics) = 0;
virtual ANAStats GetANAStats() const = 0;
virtual int GetTargetBitrate() const = 0;
};
} // namespace webrtc

View File

@ -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);

View File

@ -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(

View File

@ -964,7 +964,6 @@ class RTCStatsReportVerifier {
outbound_stream.header_bytes_sent);
verifier.TestMemberIsNonNegative<uint64_t>(
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<uint32_t>(outbound_stream.frames_sent);
verifier.TestMemberIsNonNegative<uint32_t>(
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<double>(outbound_stream.target_bitrate);
}
return verifier.ExpectAllMembersSuccessfullyTested();
}