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:
stefan 2017-02-07 07:14:08 -08:00 committed by Commit bot
parent 2bc6864278
commit 7de8d64f89
10 changed files with 108 additions and 40 deletions

View File

@ -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",

View File

@ -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.";
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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