Wire up audio packet loss to BWE.
BUG=webtrc:5079 Review-Url: https://codereview.webrtc.org/2658233002 Cr-Commit-Position: refs/heads/master@{#16474}
This commit is contained in:
parent
2bc6864278
commit
7de8d64f89
@ -37,6 +37,7 @@ rtc_static_library("audio") {
|
||||
"../common_audio",
|
||||
"../modules/audio_device",
|
||||
"../modules/audio_processing",
|
||||
"../modules/bitrate_controller:bitrate_controller",
|
||||
"../modules/congestion_controller:congestion_controller",
|
||||
"../modules/pacing:pacing",
|
||||
"../modules/remote_bitrate_estimator:remote_bitrate_estimator",
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include "webrtc/base/event.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/base/task_queue.h"
|
||||
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
|
||||
#include "webrtc/modules/congestion_controller/include/congestion_controller.h"
|
||||
#include "webrtc/modules/pacing/paced_sender.h"
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||
@ -62,9 +63,6 @@ AudioSendStream::AudioSendStream(
|
||||
channel_proxy_ = voe_impl->GetChannelProxy(config_.voe_channel_id);
|
||||
channel_proxy_->SetRtcEventLog(event_log);
|
||||
channel_proxy_->SetRtcpRttStats(rtcp_rtt_stats);
|
||||
channel_proxy_->RegisterSenderCongestionControlObjects(
|
||||
congestion_controller->pacer(),
|
||||
congestion_controller->GetTransportFeedbackObserver(), packet_router);
|
||||
channel_proxy_->SetRTCPStatus(true);
|
||||
channel_proxy_->SetLocalSSRC(config.rtp.ssrc);
|
||||
channel_proxy_->SetRTCP_CNAME(config.rtp.c_name);
|
||||
@ -81,10 +79,16 @@ AudioSendStream::AudioSendStream(
|
||||
} else if (extension.uri == RtpExtension::kTransportSequenceNumberUri) {
|
||||
channel_proxy_->EnableSendTransportSequenceNumber(extension.id);
|
||||
congestion_controller->EnablePeriodicAlrProbing(true);
|
||||
bandwidth_observer_.reset(congestion_controller->GetBitrateController()
|
||||
->CreateRtcpBandwidthObserver());
|
||||
} else {
|
||||
RTC_NOTREACHED() << "Registering unsupported RTP extension.";
|
||||
}
|
||||
}
|
||||
channel_proxy_->RegisterSenderCongestionControlObjects(
|
||||
congestion_controller->pacer(),
|
||||
congestion_controller->GetTransportFeedbackObserver(), packet_router,
|
||||
bandwidth_observer_.get());
|
||||
if (!SetupSendCodec()) {
|
||||
LOG(LS_ERROR) << "Failed to set up send codec state.";
|
||||
}
|
||||
|
||||
@ -23,6 +23,7 @@ namespace webrtc {
|
||||
class CongestionController;
|
||||
class VoiceEngine;
|
||||
class RtcEventLog;
|
||||
class RtcpBandwidthObserver;
|
||||
class RtcpRttStats;
|
||||
class PacketRouter;
|
||||
|
||||
@ -77,6 +78,7 @@ class AudioSendStream final : public webrtc::AudioSendStream,
|
||||
|
||||
BitrateAllocator* const bitrate_allocator_;
|
||||
CongestionController* const congestion_controller_;
|
||||
std::unique_ptr<RtcpBandwidthObserver> bandwidth_observer_;
|
||||
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioSendStream);
|
||||
};
|
||||
|
||||
@ -32,6 +32,8 @@ namespace test {
|
||||
namespace {
|
||||
|
||||
using testing::_;
|
||||
using testing::Eq;
|
||||
using testing::Ne;
|
||||
using testing::Return;
|
||||
|
||||
const int kChannelId = 1;
|
||||
@ -62,7 +64,7 @@ class MockLimitObserver : public BitrateAllocator::LimitObserver {
|
||||
};
|
||||
|
||||
struct ConfigHelper {
|
||||
ConfigHelper()
|
||||
explicit ConfigHelper(bool audio_bwe_enabled)
|
||||
: simulated_clock_(123456),
|
||||
stream_config_(nullptr),
|
||||
congestion_controller_(&simulated_clock_,
|
||||
@ -87,7 +89,7 @@ struct ConfigHelper {
|
||||
config.audio_mixer = AudioMixerImpl::Create();
|
||||
audio_state_ = AudioState::Create(config);
|
||||
|
||||
SetupDefaultChannelProxy();
|
||||
SetupDefaultChannelProxy(audio_bwe_enabled);
|
||||
|
||||
EXPECT_CALL(voice_engine_, ChannelProxyFactory(kChannelId))
|
||||
.WillOnce(Invoke([this](int channel_id) {
|
||||
@ -102,8 +104,12 @@ struct ConfigHelper {
|
||||
stream_config_.rtp.c_name = kCName;
|
||||
stream_config_.rtp.extensions.push_back(
|
||||
RtpExtension(RtpExtension::kAudioLevelUri, kAudioLevelId));
|
||||
stream_config_.rtp.extensions.push_back(RtpExtension(
|
||||
RtpExtension::kTransportSequenceNumberUri, kTransportSequenceNumberId));
|
||||
if (audio_bwe_enabled) {
|
||||
stream_config_.rtp.extensions.push_back(
|
||||
RtpExtension(RtpExtension::kTransportSequenceNumberUri,
|
||||
kTransportSequenceNumberId));
|
||||
stream_config_.send_codec_spec.transport_cc_enabled = true;
|
||||
}
|
||||
// Use ISAC as default codec so as to prevent unnecessary |voice_engine_|
|
||||
// calls from the default ctor behavior.
|
||||
stream_config_.send_codec_spec.codec_inst = kIsacCodec;
|
||||
@ -123,7 +129,7 @@ struct ConfigHelper {
|
||||
RtcEventLog* event_log() { return &event_log_; }
|
||||
MockVoiceEngine* voice_engine() { return &voice_engine_; }
|
||||
|
||||
void SetupDefaultChannelProxy() {
|
||||
void SetupDefaultChannelProxy(bool audio_bwe_enabled) {
|
||||
using testing::StrEq;
|
||||
channel_proxy_ = new testing::StrictMock<MockVoEChannelProxy>();
|
||||
EXPECT_CALL(*channel_proxy_, SetRTCPStatus(true)).Times(1);
|
||||
@ -133,15 +139,25 @@ struct ConfigHelper {
|
||||
EXPECT_CALL(*channel_proxy_,
|
||||
SetSendAudioLevelIndicationStatus(true, kAudioLevelId))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*channel_proxy_,
|
||||
EnableSendTransportSequenceNumber(kTransportSequenceNumberId))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*channel_proxy_,
|
||||
RegisterSenderCongestionControlObjects(
|
||||
congestion_controller_.pacer(),
|
||||
congestion_controller_.GetTransportFeedbackObserver(),
|
||||
packet_router()))
|
||||
.Times(1);
|
||||
|
||||
if (audio_bwe_enabled) {
|
||||
EXPECT_CALL(*channel_proxy_,
|
||||
EnableSendTransportSequenceNumber(kTransportSequenceNumberId))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*channel_proxy_,
|
||||
RegisterSenderCongestionControlObjects(
|
||||
congestion_controller_.pacer(),
|
||||
congestion_controller_.GetTransportFeedbackObserver(),
|
||||
packet_router(), Ne(nullptr)))
|
||||
.Times(1);
|
||||
} else {
|
||||
EXPECT_CALL(*channel_proxy_,
|
||||
RegisterSenderCongestionControlObjects(
|
||||
congestion_controller_.pacer(),
|
||||
congestion_controller_.GetTransportFeedbackObserver(),
|
||||
packet_router(), Eq(nullptr)))
|
||||
.Times(1);
|
||||
}
|
||||
EXPECT_CALL(*channel_proxy_, ResetCongestionControlObjects()).Times(1);
|
||||
EXPECT_CALL(*channel_proxy_, RegisterExternalTransport(nullptr)).Times(1);
|
||||
EXPECT_CALL(*channel_proxy_, DeRegisterExternalTransport()).Times(1);
|
||||
@ -271,7 +287,7 @@ TEST(AudioSendStreamTest, ConfigToString) {
|
||||
}
|
||||
|
||||
TEST(AudioSendStreamTest, ConstructDestruct) {
|
||||
ConfigHelper helper;
|
||||
ConfigHelper helper(false);
|
||||
internal::AudioSendStream send_stream(
|
||||
helper.config(), helper.audio_state(), helper.worker_queue(),
|
||||
helper.packet_router(), helper.congestion_controller(),
|
||||
@ -279,7 +295,7 @@ TEST(AudioSendStreamTest, ConstructDestruct) {
|
||||
}
|
||||
|
||||
TEST(AudioSendStreamTest, SendTelephoneEvent) {
|
||||
ConfigHelper helper;
|
||||
ConfigHelper helper(false);
|
||||
internal::AudioSendStream send_stream(
|
||||
helper.config(), helper.audio_state(), helper.worker_queue(),
|
||||
helper.packet_router(), helper.congestion_controller(),
|
||||
@ -291,7 +307,7 @@ TEST(AudioSendStreamTest, SendTelephoneEvent) {
|
||||
}
|
||||
|
||||
TEST(AudioSendStreamTest, SetMuted) {
|
||||
ConfigHelper helper;
|
||||
ConfigHelper helper(false);
|
||||
internal::AudioSendStream send_stream(
|
||||
helper.config(), helper.audio_state(), helper.worker_queue(),
|
||||
helper.packet_router(), helper.congestion_controller(),
|
||||
@ -300,8 +316,24 @@ TEST(AudioSendStreamTest, SetMuted) {
|
||||
send_stream.SetMuted(true);
|
||||
}
|
||||
|
||||
TEST(AudioSendStreamTest, AudioBweCorrectObjectsOnChannelProxy) {
|
||||
ConfigHelper helper(true);
|
||||
internal::AudioSendStream send_stream(
|
||||
helper.config(), helper.audio_state(), helper.worker_queue(),
|
||||
helper.packet_router(), helper.congestion_controller(),
|
||||
helper.bitrate_allocator(), helper.event_log(), helper.rtcp_rtt_stats());
|
||||
}
|
||||
|
||||
TEST(AudioSendStreamTest, NoAudioBweCorrectObjectsOnChannelProxy) {
|
||||
ConfigHelper helper(false);
|
||||
internal::AudioSendStream send_stream(
|
||||
helper.config(), helper.audio_state(), helper.worker_queue(),
|
||||
helper.packet_router(), helper.congestion_controller(),
|
||||
helper.bitrate_allocator(), helper.event_log(), helper.rtcp_rtt_stats());
|
||||
}
|
||||
|
||||
TEST(AudioSendStreamTest, GetStats) {
|
||||
ConfigHelper helper;
|
||||
ConfigHelper helper(false);
|
||||
internal::AudioSendStream send_stream(
|
||||
helper.config(), helper.audio_state(), helper.worker_queue(),
|
||||
helper.packet_router(), helper.congestion_controller(),
|
||||
@ -332,7 +364,7 @@ TEST(AudioSendStreamTest, GetStats) {
|
||||
}
|
||||
|
||||
TEST(AudioSendStreamTest, GetStatsTypingNoiseDetected) {
|
||||
ConfigHelper helper;
|
||||
ConfigHelper helper(false);
|
||||
internal::AudioSendStream send_stream(
|
||||
helper.config(), helper.audio_state(), helper.worker_queue(),
|
||||
helper.packet_router(), helper.congestion_controller(),
|
||||
@ -351,7 +383,7 @@ TEST(AudioSendStreamTest, GetStatsTypingNoiseDetected) {
|
||||
}
|
||||
|
||||
TEST(AudioSendStreamTest, SendCodecAppliesConfigParams) {
|
||||
ConfigHelper helper;
|
||||
ConfigHelper helper(false);
|
||||
auto stream_config = helper.config();
|
||||
const CodecInst kOpusCodec = {111, "opus", 48000, 960, 2, 64000};
|
||||
stream_config.send_codec_spec.codec_inst = kOpusCodec;
|
||||
@ -396,7 +428,7 @@ TEST(AudioSendStreamTest, SendCodecAppliesConfigParams) {
|
||||
// VAD is applied when codec is mono and the CNG frequency matches the codec
|
||||
// sample rate.
|
||||
TEST(AudioSendStreamTest, SendCodecCanApplyVad) {
|
||||
ConfigHelper helper;
|
||||
ConfigHelper helper(false);
|
||||
auto stream_config = helper.config();
|
||||
const CodecInst kG722Codec = {9, "g722", 8000, 160, 1, 16000};
|
||||
stream_config.send_codec_spec.codec_inst = kG722Codec;
|
||||
@ -411,7 +443,7 @@ TEST(AudioSendStreamTest, SendCodecCanApplyVad) {
|
||||
}
|
||||
|
||||
TEST(AudioSendStreamTest, DoesNotPassHigherBitrateThanMaxBitrate) {
|
||||
ConfigHelper helper;
|
||||
ConfigHelper helper(false);
|
||||
internal::AudioSendStream send_stream(
|
||||
helper.config(), helper.audio_state(), helper.worker_queue(),
|
||||
helper.packet_router(), helper.congestion_controller(),
|
||||
@ -423,7 +455,7 @@ TEST(AudioSendStreamTest, DoesNotPassHigherBitrateThanMaxBitrate) {
|
||||
}
|
||||
|
||||
TEST(AudioSendStreamTest, ProbingIntervalOnBitrateUpdated) {
|
||||
ConfigHelper helper;
|
||||
ConfigHelper helper(false);
|
||||
internal::AudioSendStream send_stream(
|
||||
helper.config(), helper.audio_state(), helper.worker_queue(),
|
||||
helper.packet_router(), helper.congestion_controller(),
|
||||
|
||||
@ -29,10 +29,11 @@ class MockVoEChannelProxy : public voe::ChannelProxy {
|
||||
MOCK_METHOD2(SetReceiveAudioLevelIndicationStatus, void(bool enable, int id));
|
||||
MOCK_METHOD1(EnableSendTransportSequenceNumber, void(int id));
|
||||
MOCK_METHOD1(EnableReceiveTransportSequenceNumber, void(int id));
|
||||
MOCK_METHOD3(RegisterSenderCongestionControlObjects,
|
||||
MOCK_METHOD4(RegisterSenderCongestionControlObjects,
|
||||
void(RtpPacketSender* rtp_packet_sender,
|
||||
TransportFeedbackObserver* transport_feedback_observer,
|
||||
PacketRouter* packet_router));
|
||||
PacketRouter* packet_router,
|
||||
RtcpBandwidthObserver* bandwidth_observer));
|
||||
MOCK_METHOD1(RegisterReceiverCongestionControlObjects,
|
||||
void(PacketRouter* packet_router));
|
||||
MOCK_METHOD0(ResetCongestionControlObjects, void());
|
||||
|
||||
@ -927,6 +927,8 @@ std::string VideoQualityTest::GenerateGraphTitle() const {
|
||||
}
|
||||
|
||||
void VideoQualityTest::CheckParams() {
|
||||
if (!params_.video.enabled)
|
||||
return;
|
||||
// Add a default stream in none specified.
|
||||
if (params_.ss.streams.empty())
|
||||
params_.ss.streams.push_back(VideoQualityTest::DefaultVideoStream(params_));
|
||||
|
||||
@ -333,16 +333,32 @@ class StatisticsProxy : public RtcpStatisticsCallback {
|
||||
|
||||
class VoERtcpObserver : public RtcpBandwidthObserver {
|
||||
public:
|
||||
explicit VoERtcpObserver(Channel* owner) : owner_(owner) {}
|
||||
explicit VoERtcpObserver(Channel* owner)
|
||||
: owner_(owner), bandwidth_observer_(nullptr) {}
|
||||
virtual ~VoERtcpObserver() {}
|
||||
|
||||
void SetBandwidthObserver(RtcpBandwidthObserver* bandwidth_observer) {
|
||||
rtc::CritScope lock(&crit_);
|
||||
bandwidth_observer_ = bandwidth_observer;
|
||||
}
|
||||
|
||||
void OnReceivedEstimatedBitrate(uint32_t bitrate) override {
|
||||
// Not used for Voice Engine.
|
||||
rtc::CritScope lock(&crit_);
|
||||
if (bandwidth_observer_) {
|
||||
bandwidth_observer_->OnReceivedEstimatedBitrate(bitrate);
|
||||
}
|
||||
}
|
||||
|
||||
void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks,
|
||||
int64_t rtt,
|
||||
int64_t now_ms) override {
|
||||
{
|
||||
rtc::CritScope lock(&crit_);
|
||||
if (bandwidth_observer_) {
|
||||
bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, rtt,
|
||||
now_ms);
|
||||
}
|
||||
}
|
||||
// TODO(mflodman): Do we need to aggregate reports here or can we jut send
|
||||
// what we get? I.e. do we ever get multiple reports bundled into one RTCP
|
||||
// report for VoiceEngine?
|
||||
@ -384,6 +400,8 @@ class VoERtcpObserver : public RtcpBandwidthObserver {
|
||||
Channel* owner_;
|
||||
// Maps remote side ssrc to extended highest sequence number received.
|
||||
std::map<uint32_t, uint32_t> extended_max_sequence_number_;
|
||||
rtc::CriticalSection crit_;
|
||||
RtcpBandwidthObserver* bandwidth_observer_ GUARDED_BY(crit_);
|
||||
};
|
||||
|
||||
int32_t Channel::SendData(FrameType frameType,
|
||||
@ -2424,10 +2442,12 @@ void Channel::EnableReceiveTransportSequenceNumber(int id) {
|
||||
void Channel::RegisterSenderCongestionControlObjects(
|
||||
RtpPacketSender* rtp_packet_sender,
|
||||
TransportFeedbackObserver* transport_feedback_observer,
|
||||
PacketRouter* packet_router) {
|
||||
PacketRouter* packet_router,
|
||||
RtcpBandwidthObserver* bandwidth_observer) {
|
||||
RTC_DCHECK(rtp_packet_sender);
|
||||
RTC_DCHECK(transport_feedback_observer);
|
||||
RTC_DCHECK(packet_router && !packet_router_);
|
||||
rtcp_observer_->SetBandwidthObserver(bandwidth_observer);
|
||||
feedback_observer_proxy_->SetTransportFeedbackObserver(
|
||||
transport_feedback_observer);
|
||||
seq_num_allocator_proxy_->SetSequenceNumberAllocator(packet_router);
|
||||
@ -2447,6 +2467,7 @@ void Channel::RegisterReceiverCongestionControlObjects(
|
||||
void Channel::ResetCongestionControlObjects() {
|
||||
RTC_DCHECK(packet_router_);
|
||||
_rtpRtcpModule->SetStorePacketsStatus(false, 600);
|
||||
rtcp_observer_->SetBandwidthObserver(nullptr);
|
||||
feedback_observer_proxy_->SetTransportFeedbackObserver(nullptr);
|
||||
seq_num_allocator_proxy_->SetSequenceNumberAllocator(nullptr);
|
||||
packet_router_->RemoveRtpModule(_rtpRtcpModule.get());
|
||||
|
||||
@ -304,12 +304,13 @@ class Channel
|
||||
void EnableSendTransportSequenceNumber(int id);
|
||||
void EnableReceiveTransportSequenceNumber(int id);
|
||||
|
||||
void RegisterSenderCongestionControlObjects(
|
||||
RtpPacketSender* rtp_packet_sender,
|
||||
TransportFeedbackObserver* transport_feedback_observer,
|
||||
PacketRouter* packet_router);
|
||||
void RegisterReceiverCongestionControlObjects(PacketRouter* packet_router);
|
||||
void ResetCongestionControlObjects();
|
||||
void RegisterSenderCongestionControlObjects(
|
||||
RtpPacketSender* rtp_packet_sender,
|
||||
TransportFeedbackObserver* transport_feedback_observer,
|
||||
PacketRouter* packet_router,
|
||||
RtcpBandwidthObserver* bandwidth_observer);
|
||||
void RegisterReceiverCongestionControlObjects(PacketRouter* packet_router);
|
||||
void ResetCongestionControlObjects();
|
||||
|
||||
void SetRTCPStatus(bool enable);
|
||||
int GetRTCPStatus(bool& enabled);
|
||||
|
||||
@ -75,10 +75,12 @@ void ChannelProxy::EnableReceiveTransportSequenceNumber(int id) {
|
||||
void ChannelProxy::RegisterSenderCongestionControlObjects(
|
||||
RtpPacketSender* rtp_packet_sender,
|
||||
TransportFeedbackObserver* transport_feedback_observer,
|
||||
PacketRouter* packet_router) {
|
||||
PacketRouter* packet_router,
|
||||
RtcpBandwidthObserver* bandwidth_observer) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
channel()->RegisterSenderCongestionControlObjects(
|
||||
rtp_packet_sender, transport_feedback_observer, packet_router);
|
||||
rtp_packet_sender, transport_feedback_observer, packet_router,
|
||||
bandwidth_observer);
|
||||
}
|
||||
|
||||
void ChannelProxy::RegisterReceiverCongestionControlObjects(
|
||||
|
||||
@ -27,6 +27,7 @@ namespace webrtc {
|
||||
class AudioSinkInterface;
|
||||
class PacketRouter;
|
||||
class RtcEventLog;
|
||||
class RtcpBandwidthObserver;
|
||||
class RtcpRttStats;
|
||||
class RtpPacketSender;
|
||||
class RtpReceiver;
|
||||
@ -62,7 +63,8 @@ class ChannelProxy {
|
||||
virtual void RegisterSenderCongestionControlObjects(
|
||||
RtpPacketSender* rtp_packet_sender,
|
||||
TransportFeedbackObserver* transport_feedback_observer,
|
||||
PacketRouter* packet_router);
|
||||
PacketRouter* packet_router,
|
||||
RtcpBandwidthObserver* bandwidth_observer);
|
||||
virtual void RegisterReceiverCongestionControlObjects(
|
||||
PacketRouter* packet_router);
|
||||
virtual void ResetCongestionControlObjects();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user