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:

committed by
WebRTC LUCI CQ

parent
1d73243466
commit
bf0874568c
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 =
|
||||
|
@ -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) {
|
||||
|
@ -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(
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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(
|
||||
|
@ -237,6 +237,8 @@ class AudioCodingModule {
|
||||
NetworkStatistics* network_statistics) = 0;
|
||||
|
||||
virtual ANAStats GetANAStats() const = 0;
|
||||
|
||||
virtual int GetTargetBitrate() const = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -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);
|
||||
|
@ -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(
|
||||
|
@ -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();
|
||||
}
|
||||
|
Reference in New Issue
Block a user