Prepare the AudioSendStream to be hooked up to send-side BWE.
This CL contains three changes as a preparation for adding audio send streams
to the send-side BWE:
1. Audio packets are passed through the pacer with high priority. This
is needed to be able to set transport sequence numbers on the packets.
2. A feedback observer is passed to the audio stream's rtcp receiver so
that the BWE can get notified of any BWE feedback being received on the
audio feedback channel.
3. Support for the transport sequence number header extension is added
to audio send streams.
BUG=webrtc:5263,webrtc:5307
R=mflodman@webrtc.org, solenberg@webrtc.org
Review URL: https://codereview.webrtc.org/1479023002 .
Cr-Original-Commit-Position: refs/heads/master@{#10909}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: b86d4e4a8dec1eb1b801244a2a97cda66f561d8e
diff --git a/audio/audio_send_stream.cc b/audio/audio_send_stream.cc
index 2ff388b..35a6552 100644
--- a/audio/audio_send_stream.cc
+++ b/audio/audio_send_stream.cc
@@ -17,6 +17,9 @@
#include "webrtc/audio/scoped_voe_interface.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
+#include "webrtc/call/congestion_controller.h"
+#include "webrtc/modules/pacing/paced_sender.h"
+#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "webrtc/voice_engine/channel_proxy.h"
#include "webrtc/voice_engine/include/voe_audio_processing.h"
#include "webrtc/voice_engine/include/voe_codec.h"
@@ -55,22 +58,31 @@
namespace internal {
AudioSendStream::AudioSendStream(
const webrtc::AudioSendStream::Config& config,
- const rtc::scoped_refptr<webrtc::AudioState>& audio_state)
+ const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
+ CongestionController* congestion_controller)
: config_(config), audio_state_(audio_state) {
LOG(LS_INFO) << "AudioSendStream: " << config_.ToString();
RTC_DCHECK_NE(config_.voe_channel_id, -1);
RTC_DCHECK(audio_state_.get());
+ RTC_DCHECK(congestion_controller);
VoiceEngineImpl* voe_impl = static_cast<VoiceEngineImpl*>(voice_engine());
channel_proxy_ = voe_impl->GetChannelProxy(config_.voe_channel_id);
+ channel_proxy_->SetCongestionControlObjects(
+ congestion_controller->pacer(),
+ congestion_controller->GetTransportFeedbackObserver(),
+ congestion_controller->packet_router());
channel_proxy_->SetRTCPStatus(true);
channel_proxy_->SetLocalSSRC(config.rtp.ssrc);
channel_proxy_->SetRTCP_CNAME(config.rtp.c_name);
+
for (const auto& extension : config.rtp.extensions) {
if (extension.name == RtpExtension::kAbsSendTime) {
channel_proxy_->SetSendAbsoluteSenderTimeStatus(true, extension.id);
} else if (extension.name == RtpExtension::kAudioLevel) {
channel_proxy_->SetSendAudioLevelIndicationStatus(true, extension.id);
+ } else if (extension.name == RtpExtension::kTransportSequenceNumber) {
+ channel_proxy_->EnableSendTransportSequenceNumber(extension.id);
} else {
RTC_NOTREACHED() << "Registering unsupported RTP extension.";
}
@@ -80,6 +92,7 @@
AudioSendStream::~AudioSendStream() {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
LOG(LS_INFO) << "~AudioSendStream: " << config_.ToString();
+ channel_proxy_->SetCongestionControlObjects(nullptr, nullptr, nullptr);
}
void AudioSendStream::Start() {
diff --git a/audio/audio_send_stream.h b/audio/audio_send_stream.h
index 88304fd..8b96350 100644
--- a/audio/audio_send_stream.h
+++ b/audio/audio_send_stream.h
@@ -17,6 +17,7 @@
#include "webrtc/base/scoped_ptr.h"
namespace webrtc {
+class CongestionController;
class VoiceEngine;
namespace voe {
@@ -27,7 +28,8 @@
class AudioSendStream final : public webrtc::AudioSendStream {
public:
AudioSendStream(const webrtc::AudioSendStream::Config& config,
- const rtc::scoped_refptr<webrtc::AudioState>& audio_state);
+ const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
+ CongestionController* congestion_controller);
~AudioSendStream() override;
// webrtc::SendStream implementation.
diff --git a/audio/audio_send_stream_unittest.cc b/audio/audio_send_stream_unittest.cc
index c3620b2..f907575 100644
--- a/audio/audio_send_stream_unittest.cc
+++ b/audio/audio_send_stream_unittest.cc
@@ -16,8 +16,12 @@
#include "webrtc/audio/audio_send_stream.h"
#include "webrtc/audio/audio_state.h"
#include "webrtc/audio/conversion.h"
+#include "webrtc/call/congestion_controller.h"
+#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
+#include "webrtc/modules/pacing/paced_sender.h"
#include "webrtc/test/mock_voe_channel_proxy.h"
#include "webrtc/test/mock_voice_engine.h"
+#include "webrtc/video_engine/call_stats.h"
namespace webrtc {
namespace test {
@@ -31,6 +35,7 @@
const char* kCName = "foo_name";
const int kAudioLevelId = 2;
const int kAbsSendTimeId = 3;
+const int kTransportSequenceNumberId = 4;
const int kEchoDelayMedian = 254;
const int kEchoDelayStdDev = -3;
const int kEchoReturnLoss = -65;
@@ -45,7 +50,12 @@
const uint32_t kTelephoneEventDuration = 6789;
struct ConfigHelper {
- ConfigHelper() : stream_config_(nullptr) {
+ ConfigHelper()
+ : stream_config_(nullptr),
+ process_thread_(ProcessThread::Create("AudioTestThread")),
+ congestion_controller_(process_thread_.get(),
+ &call_stats_,
+ &bitrate_observer_) {
using testing::Invoke;
using testing::StrEq;
@@ -68,6 +78,18 @@
SetSendAbsoluteSenderTimeStatus(true, kAbsSendTimeId)).Times(1);
EXPECT_CALL(*channel_proxy_,
SetSendAudioLevelIndicationStatus(true, kAudioLevelId)).Times(1);
+ EXPECT_CALL(*channel_proxy_, EnableSendTransportSequenceNumber(
+ kTransportSequenceNumberId))
+ .Times(1);
+ EXPECT_CALL(*channel_proxy_,
+ SetCongestionControlObjects(
+ congestion_controller_.pacer(),
+ congestion_controller_.GetTransportFeedbackObserver(),
+ congestion_controller_.packet_router()))
+ .Times(1);
+ EXPECT_CALL(*channel_proxy_,
+ SetCongestionControlObjects(nullptr, nullptr, nullptr))
+ .Times(1);
return channel_proxy_;
}));
stream_config_.voe_channel_id = kChannelId;
@@ -77,10 +99,15 @@
RtpExtension(RtpExtension::kAudioLevel, kAudioLevelId));
stream_config_.rtp.extensions.push_back(
RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeId));
+ stream_config_.rtp.extensions.push_back(RtpExtension(
+ RtpExtension::kTransportSequenceNumber, kTransportSequenceNumberId));
}
AudioSendStream::Config& config() { return stream_config_; }
rtc::scoped_refptr<AudioState> audio_state() { return audio_state_; }
+ CongestionController* congestion_controller() {
+ return &congestion_controller_;
+ }
void SetupMockForSendTelephoneEvent() {
EXPECT_TRUE(channel_proxy_);
@@ -126,10 +153,21 @@
}
private:
+ class NullBitrateObserver : public BitrateObserver {
+ public:
+ virtual void OnNetworkChanged(uint32_t bitrate_bps,
+ uint8_t fraction_loss,
+ int64_t rtt_ms) {}
+ };
+
testing::StrictMock<MockVoiceEngine> voice_engine_;
rtc::scoped_refptr<AudioState> audio_state_;
AudioSendStream::Config stream_config_;
testing::StrictMock<MockVoEChannelProxy>* channel_proxy_ = nullptr;
+ CallStats call_stats_;
+ NullBitrateObserver bitrate_observer_;
+ rtc::scoped_ptr<ProcessThread> process_thread_;
+ CongestionController congestion_controller_;
};
} // namespace
@@ -152,12 +190,14 @@
TEST(AudioSendStreamTest, ConstructDestruct) {
ConfigHelper helper;
- internal::AudioSendStream send_stream(helper.config(), helper.audio_state());
+ internal::AudioSendStream send_stream(helper.config(), helper.audio_state(),
+ helper.congestion_controller());
}
TEST(AudioSendStreamTest, SendTelephoneEvent) {
ConfigHelper helper;
- internal::AudioSendStream send_stream(helper.config(), helper.audio_state());
+ internal::AudioSendStream send_stream(helper.config(), helper.audio_state(),
+ helper.congestion_controller());
helper.SetupMockForSendTelephoneEvent();
EXPECT_TRUE(send_stream.SendTelephoneEvent(kTelephoneEventPayloadType,
kTelephoneEventCode, kTelephoneEventDuration));
@@ -165,7 +205,8 @@
TEST(AudioSendStreamTest, GetStats) {
ConfigHelper helper;
- internal::AudioSendStream send_stream(helper.config(), helper.audio_state());
+ internal::AudioSendStream send_stream(helper.config(), helper.audio_state(),
+ helper.congestion_controller());
helper.SetupMockForGetStats();
AudioSendStream::Stats stats = send_stream.GetStats();
EXPECT_EQ(kSsrc, stats.local_ssrc);
@@ -192,7 +233,8 @@
TEST(AudioSendStreamTest, GetStatsTypingNoiseDetected) {
ConfigHelper helper;
- internal::AudioSendStream send_stream(helper.config(), helper.audio_state());
+ internal::AudioSendStream send_stream(helper.config(), helper.audio_state(),
+ helper.congestion_controller());
helper.SetupMockForGetStats();
EXPECT_FALSE(send_stream.GetStats().typing_noise_detected);
diff --git a/audio_send_stream.h b/audio_send_stream.h
index dd8d9e9..d1af9e0 100644
--- a/audio_send_stream.h
+++ b/audio_send_stream.h
@@ -64,7 +64,7 @@
// Sender SSRC.
uint32_t ssrc = 0;
- // RTP header extensions used for the received stream.
+ // RTP header extensions used for the sent stream.
std::vector<RtpExtension> extensions;
// RTCP CNAME, see RFC 3550.
diff --git a/call/call.cc b/call/call.cc
index 4156765..9209c7c 100644
--- a/call/call.cc
+++ b/call/call.cc
@@ -300,8 +300,8 @@
const webrtc::AudioSendStream::Config& config) {
TRACE_EVENT0("webrtc", "Call::CreateAudioSendStream");
RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
- AudioSendStream* send_stream =
- new AudioSendStream(config, config_.audio_state);
+ AudioSendStream* send_stream = new AudioSendStream(
+ config, config_.audio_state, congestion_controller_.get());
if (!network_enabled_)
send_stream->SignalNetworkState(kNetworkDown);
{
diff --git a/call/call_perf_tests.cc b/call/call_perf_tests.cc
index 44ecae3..caa5482 100644
--- a/call/call_perf_tests.cc
+++ b/call/call_perf_tests.cc
@@ -18,6 +18,8 @@
#include "webrtc/base/thread_annotations.h"
#include "webrtc/call.h"
#include "webrtc/call/transport_adapter.h"
+#include "webrtc/common.h"
+#include "webrtc/config.h"
#include "webrtc/modules/audio_coding/include/audio_coding_module.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
@@ -189,6 +191,8 @@
void CallPerfTest::TestAudioVideoSync(bool fec, bool create_audio_first) {
const char* kSyncGroup = "av_sync";
+ const uint32_t kAudioSendSsrc = 1234;
+ const uint32_t kAudioRecvSsrc = 5678;
class AudioPacketReceiver : public PacketReceiver {
public:
AudioPacketReceiver(int channel, VoENetwork* voe_network)
@@ -228,37 +232,45 @@
test::FakeAudioDevice fake_audio_device(Clock::GetRealTimeClock(),
audio_filename);
EXPECT_EQ(0, voe_base->Init(&fake_audio_device, nullptr));
- int channel = voe_base->CreateChannel();
+ Config voe_config;
+ voe_config.Set<VoicePacing>(new VoicePacing(true));
+ int send_channel_id = voe_base->CreateChannel(voe_config);
+ int recv_channel_id = voe_base->CreateChannel();
SyncRtcpObserver audio_observer;
- AudioState::Config audio_state_config;
- audio_state_config.voice_engine = voice_engine;
+ AudioState::Config send_audio_state_config;
+ send_audio_state_config.voice_engine = voice_engine;
+ Call::Config sender_config;
+ sender_config.audio_state = AudioState::Create(send_audio_state_config);
Call::Config receiver_config;
- receiver_config.audio_state = AudioState::Create(audio_state_config);
- CreateCalls(Call::Config(), receiver_config);
+ receiver_config.audio_state = sender_config.audio_state;
+ CreateCalls(sender_config, receiver_config);
- CodecInst isac = {103, "ISAC", 16000, 480, 1, 32000};
- EXPECT_EQ(0, voe_codec->SetSendCodec(channel, isac));
-
- AudioPacketReceiver voe_packet_receiver(channel, voe_network);
+ AudioPacketReceiver voe_send_packet_receiver(send_channel_id, voe_network);
+ AudioPacketReceiver voe_recv_packet_receiver(recv_channel_id, voe_network);
FakeNetworkPipe::Config net_config;
net_config.queue_delay_ms = 500;
net_config.loss_percent = 5;
test::PacketTransport audio_send_transport(
nullptr, &audio_observer, test::PacketTransport::kSender, net_config);
- audio_send_transport.SetReceiver(&voe_packet_receiver);
+ audio_send_transport.SetReceiver(&voe_recv_packet_receiver);
test::PacketTransport audio_receive_transport(
nullptr, &audio_observer, test::PacketTransport::kReceiver, net_config);
- audio_receive_transport.SetReceiver(&voe_packet_receiver);
+ audio_receive_transport.SetReceiver(&voe_send_packet_receiver);
- internal::TransportAdapter transport_adapter(&audio_send_transport);
- transport_adapter.Enable();
- EXPECT_EQ(0,
- voe_network->RegisterExternalTransport(channel, transport_adapter));
+ internal::TransportAdapter send_transport_adapter(&audio_send_transport);
+ send_transport_adapter.Enable();
+ EXPECT_EQ(0, voe_network->RegisterExternalTransport(send_channel_id,
+ send_transport_adapter));
- VideoRtcpAndSyncObserver observer(Clock::GetRealTimeClock(), channel,
+ internal::TransportAdapter recv_transport_adapter(&audio_receive_transport);
+ recv_transport_adapter.Enable();
+ EXPECT_EQ(0, voe_network->RegisterExternalTransport(recv_channel_id,
+ recv_transport_adapter));
+
+ VideoRtcpAndSyncObserver observer(Clock::GetRealTimeClock(), recv_channel_id,
voe_sync, &audio_observer);
test::PacketTransport sync_send_transport(sender_call_.get(), &observer,
@@ -275,6 +287,15 @@
CreateSendConfig(1, &sync_send_transport);
CreateMatchingReceiveConfigs(&sync_receive_transport);
+ AudioSendStream::Config audio_send_config(&audio_send_transport);
+ audio_send_config.voe_channel_id = send_channel_id;
+ audio_send_config.rtp.ssrc = kAudioSendSsrc;
+ AudioSendStream* audio_send_stream =
+ sender_call_->CreateAudioSendStream(audio_send_config);
+
+ CodecInst isac = {103, "ISAC", 16000, 480, 1, 32000};
+ EXPECT_EQ(0, voe_codec->SetSendCodec(send_channel_id, isac));
+
send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
if (fec) {
send_config_.rtp.fec.red_payload_type = kRedPayloadType;
@@ -286,20 +307,22 @@
receive_configs_[0].renderer = &observer;
receive_configs_[0].sync_group = kSyncGroup;
- AudioReceiveStream::Config audio_config;
- audio_config.voe_channel_id = channel;
- audio_config.sync_group = kSyncGroup;
+ AudioReceiveStream::Config audio_recv_config;
+ audio_recv_config.rtp.remote_ssrc = kAudioSendSsrc;
+ audio_recv_config.rtp.local_ssrc = kAudioRecvSsrc;
+ audio_recv_config.voe_channel_id = recv_channel_id;
+ audio_recv_config.sync_group = kSyncGroup;
- AudioReceiveStream* audio_receive_stream = nullptr;
+ AudioReceiveStream* audio_receive_stream;
if (create_audio_first) {
audio_receive_stream =
- receiver_call_->CreateAudioReceiveStream(audio_config);
+ receiver_call_->CreateAudioReceiveStream(audio_recv_config);
CreateStreams();
} else {
CreateStreams();
audio_receive_stream =
- receiver_call_->CreateAudioReceiveStream(audio_config);
+ receiver_call_->CreateAudioReceiveStream(audio_recv_config);
}
CreateFrameGeneratorCapturer();
@@ -307,16 +330,16 @@
Start();
fake_audio_device.Start();
- EXPECT_EQ(0, voe_base->StartPlayout(channel));
- EXPECT_EQ(0, voe_base->StartReceive(channel));
- EXPECT_EQ(0, voe_base->StartSend(channel));
+ EXPECT_EQ(0, voe_base->StartPlayout(recv_channel_id));
+ EXPECT_EQ(0, voe_base->StartReceive(recv_channel_id));
+ EXPECT_EQ(0, voe_base->StartSend(send_channel_id));
EXPECT_EQ(kEventSignaled, observer.Wait())
<< "Timed out while waiting for audio and video to be synchronized.";
- EXPECT_EQ(0, voe_base->StopSend(channel));
- EXPECT_EQ(0, voe_base->StopReceive(channel));
- EXPECT_EQ(0, voe_base->StopPlayout(channel));
+ EXPECT_EQ(0, voe_base->StopSend(send_channel_id));
+ EXPECT_EQ(0, voe_base->StopReceive(recv_channel_id));
+ EXPECT_EQ(0, voe_base->StopPlayout(recv_channel_id));
fake_audio_device.Stop();
Stop();
@@ -325,16 +348,18 @@
audio_send_transport.StopSending();
audio_receive_transport.StopSending();
- voe_base->DeleteChannel(channel);
+ DestroyStreams();
+
+ sender_call_->DestroyAudioSendStream(audio_send_stream);
+ receiver_call_->DestroyAudioReceiveStream(audio_receive_stream);
+
+ voe_base->DeleteChannel(send_channel_id);
+ voe_base->DeleteChannel(recv_channel_id);
voe_base->Release();
voe_codec->Release();
voe_network->Release();
voe_sync->Release();
- DestroyStreams();
-
- receiver_call_->DestroyAudioReceiveStream(audio_receive_stream);
-
DestroyCalls();
VoiceEngine::Delete(voice_engine);
diff --git a/config.h b/config.h
index 114303e..45a2ece 100644
--- a/config.h
+++ b/config.h
@@ -138,6 +138,12 @@
bool enabled;
};
+struct VoicePacing {
+ VoicePacing() : enabled(false) {}
+ explicit VoicePacing(bool value) : enabled(value) {}
+ bool enabled;
+};
+
} // namespace webrtc
#endif // WEBRTC_CONFIG_H_
diff --git a/modules/pacing/paced_sender.cc b/modules/pacing/paced_sender.cc
index 37e8ed7..bfa6b53 100644
--- a/modules/pacing/paced_sender.cc
+++ b/modules/pacing/paced_sender.cc
@@ -358,10 +358,9 @@
CriticalSectionScoped cs(critsect_.get());
int64_t elapsed_time_ms = (now_us - time_last_update_us_ + 500) / 1000;
time_last_update_us_ = now_us;
- if (paused_)
- return 0;
int target_bitrate_kbps = max_bitrate_kbps_;
- if (elapsed_time_ms > 0) {
+ // TODO(holmer): Remove the !paused_ check when issue 5307 has been fixed.
+ if (!paused_ && elapsed_time_ms > 0) {
size_t queue_size_bytes = packets_->SizeInBytes();
if (queue_size_bytes > 0) {
// Assuming equal size packets and input/output rate, the average packet
@@ -389,7 +388,11 @@
// element from the priority queue but keep it in storage, so that we can
// reinsert it if send fails.
const paced_sender::Packet& packet = packets_->BeginPop();
- if (SendPacket(packet)) {
+
+ // TODO(holmer): Because of this bug issue 5307 we have to send audio
+ // packets even when the pacer is paused. Here we assume audio packets are
+ // always high priority and that they are the only high priority packets.
+ if ((!paused_ || packet.priority == kHighPriority) && SendPacket(packet)) {
// Send succeeded, remove it from the queue.
packets_->FinalizePop(packet);
if (prober_->IsProbing())
@@ -401,7 +404,8 @@
}
}
- if (!packets_->Empty())
+ // TODO(holmer): Remove the paused_ check when issue 5307 has been fixed.
+ if (paused_ || !packets_->Empty())
return 0;
size_t padding_needed;
diff --git a/modules/rtp_rtcp/source/rtp_sender.cc b/modules/rtp_rtcp/source/rtp_sender.cc
index dc544fb..d004cd8 100644
--- a/modules/rtp_rtcp/source/rtp_sender.cc
+++ b/modules/rtp_rtcp/source/rtp_sender.cc
@@ -469,7 +469,8 @@
std::map<int8_t, RtpUtility::Payload*>::iterator it =
payload_type_map_.find(payload_type);
if (it == payload_type_map_.end()) {
- LOG(LS_WARNING) << "Payload type " << payload_type << " not registered.";
+ LOG(LS_WARNING) << "Payload type " << static_cast<int>(payload_type)
+ << " not registered.";
return -1;
}
SetSendPayloadType(payload_type);
@@ -512,7 +513,8 @@
}
RtpVideoCodecTypes video_type = kRtpVideoGeneric;
if (CheckPayloadType(payload_type, &video_type) != 0) {
- LOG(LS_ERROR) << "Don't send data with unknown payload type.";
+ LOG(LS_ERROR) << "Don't send data with unknown payload type: "
+ << static_cast<int>(payload_type) << ".";
return -1;
}
@@ -725,7 +727,7 @@
// TickTime.
int64_t corrected_capture_tims_ms = capture_time_ms + clock_delta_ms_;
paced_sender_->InsertPacket(
- RtpPacketSender::kHighPriority, header.ssrc, header.sequenceNumber,
+ RtpPacketSender::kNormalPriority, header.ssrc, header.sequenceNumber,
corrected_capture_tims_ms, length - header.headerLength, true);
return length;
@@ -1003,7 +1005,7 @@
}
size_t RTPSender::TimeToSendPadding(size_t bytes) {
- if (bytes == 0)
+ if (audio_configured_ || bytes == 0)
return 0;
{
CriticalSectionScoped cs(send_critsect_.get());
diff --git a/modules/rtp_rtcp/source/rtp_sender_audio.cc b/modules/rtp_rtcp/source/rtp_sender_audio.cc
index f5df5b3..3ae6411 100644
--- a/modules/rtp_rtcp/source/rtp_sender_audio.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_audio.cc
@@ -16,6 +16,7 @@
#include "webrtc/base/trace_event.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
+#include "webrtc/system_wrappers/include/tick_util.h"
namespace webrtc {
@@ -368,7 +369,8 @@
_rtpSender->Timestamp(), "seqnum",
_rtpSender->SequenceNumber());
return _rtpSender->SendToNetwork(dataBuffer, payloadSize, rtpHeaderLength,
- -1, kAllowRetransmission,
+ TickTime::MillisecondTimestamp(),
+ kAllowRetransmission,
RtpPacketSender::kHighPriority);
}
@@ -476,9 +478,9 @@
"Audio::SendTelephoneEvent", "timestamp",
dtmfTimeStamp, "seqnum",
_rtpSender->SequenceNumber());
- retVal = _rtpSender->SendToNetwork(dtmfbuffer, 4, 12, -1,
- kAllowRetransmission,
- RtpPacketSender::kHighPriority);
+ retVal = _rtpSender->SendToNetwork(
+ dtmfbuffer, 4, 12, TickTime::MillisecondTimestamp(),
+ kAllowRetransmission, RtpPacketSender::kHighPriority);
sendCount--;
}while (sendCount > 0 && retVal == 0);
diff --git a/modules/rtp_rtcp/source/rtp_sender_video.cc b/modules/rtp_rtcp/source/rtp_sender_video.cc
index 0209510..3e2a2b8 100644
--- a/modules/rtp_rtcp/source/rtp_sender_video.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_video.cc
@@ -104,7 +104,7 @@
StorageType storage) {
if (_rtpSender.SendToNetwork(data_buffer, payload_length, rtp_header_length,
capture_time_ms, storage,
- RtpPacketSender::kNormalPriority) == 0) {
+ RtpPacketSender::kLowPriority) == 0) {
_videoBitrate.Update(payload_length + rtp_header_length);
TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
"Video::PacketNormal", "timestamp", capture_timestamp,
@@ -150,7 +150,7 @@
if (_rtpSender.SendToNetwork(
red_packet->data(), red_packet->length() - rtp_header_length,
rtp_header_length, capture_time_ms, media_packet_storage,
- RtpPacketSender::kNormalPriority) == 0) {
+ RtpPacketSender::kLowPriority) == 0) {
_videoBitrate.Update(red_packet->length());
TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
"Video::PacketRed", "timestamp", capture_timestamp,
@@ -162,7 +162,7 @@
if (_rtpSender.SendToNetwork(
fec_packet->data(), fec_packet->length() - rtp_header_length,
rtp_header_length, capture_time_ms, fec_storage,
- RtpPacketSender::kNormalPriority) == 0) {
+ RtpPacketSender::kLowPriority) == 0) {
_fecOverheadRate.Update(fec_packet->length());
TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
"Video::PacketFec", "timestamp", capture_timestamp,
diff --git a/test/mock_voe_channel_proxy.h b/test/mock_voe_channel_proxy.h
index a0f0464..b5d79c1 100644
--- a/test/mock_voe_channel_proxy.h
+++ b/test/mock_voe_channel_proxy.h
@@ -25,8 +25,13 @@
MOCK_METHOD1(SetRTCP_CNAME, void(const std::string& c_name));
MOCK_METHOD2(SetSendAbsoluteSenderTimeStatus, void(bool enable, int id));
MOCK_METHOD2(SetSendAudioLevelIndicationStatus, void(bool enable, int id));
+ MOCK_METHOD1(EnableSendTransportSequenceNumber, void(int id));
MOCK_METHOD2(SetReceiveAbsoluteSenderTimeStatus, void(bool enable, int id));
MOCK_METHOD2(SetReceiveAudioLevelIndicationStatus, void(bool enable, int id));
+ MOCK_METHOD3(SetCongestionControlObjects,
+ void(RtpPacketSender* rtp_packet_sender,
+ TransportFeedbackObserver* transport_feedback_observer,
+ PacketRouter* seq_num_allocator));
MOCK_CONST_METHOD0(GetRTCPStatistics, CallStatistics());
MOCK_CONST_METHOD0(GetRemoteRTCPReportBlocks, std::vector<ReportBlock>());
MOCK_CONST_METHOD0(GetNetworkStatistics, NetworkStatistics());
diff --git a/voice_engine/BUILD.gn b/voice_engine/BUILD.gn
index 7a30a7b..82cd923 100644
--- a/voice_engine/BUILD.gn
+++ b/voice_engine/BUILD.gn
@@ -106,6 +106,7 @@
"../modules/audio_processing",
"../modules/bitrate_controller",
"../modules/media_file",
+ "../modules/pacing",
"../modules/rtp_rtcp",
"../modules/utility",
"../system_wrappers",
diff --git a/voice_engine/channel.cc b/voice_engine/channel.cc
index fb98356..37dc3b6 100644
--- a/voice_engine/channel.cc
+++ b/voice_engine/channel.cc
@@ -15,12 +15,14 @@
#include "webrtc/base/checks.h"
#include "webrtc/base/format_macros.h"
#include "webrtc/base/logging.h"
+#include "webrtc/base/thread_checker.h"
#include "webrtc/base/timeutils.h"
#include "webrtc/common.h"
#include "webrtc/config.h"
#include "webrtc/modules/audio_device/include/audio_device.h"
#include "webrtc/modules/audio_processing/include/audio_processing.h"
#include "webrtc/modules/include/module_common_types.h"
+#include "webrtc/modules/pacing/packet_router.h"
#include "webrtc/modules/rtp_rtcp/include/receive_statistics.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_receiver.h"
@@ -44,6 +46,104 @@
namespace webrtc {
namespace voe {
+class TransportFeedbackProxy : public TransportFeedbackObserver {
+ public:
+ TransportFeedbackProxy() : feedback_observer_(nullptr) {
+ pacer_thread_.DetachFromThread();
+ network_thread_.DetachFromThread();
+ }
+
+ void SetTransportFeedbackObserver(
+ TransportFeedbackObserver* feedback_observer) {
+ RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ rtc::CritScope lock(&crit_);
+ feedback_observer_ = feedback_observer;
+ }
+
+ // Implements TransportFeedbackObserver.
+ void AddPacket(uint16_t sequence_number,
+ size_t length,
+ bool was_paced) override {
+ RTC_DCHECK(pacer_thread_.CalledOnValidThread());
+ rtc::CritScope lock(&crit_);
+ if (feedback_observer_)
+ feedback_observer_->AddPacket(sequence_number, length, was_paced);
+ }
+ void OnTransportFeedback(const rtcp::TransportFeedback& feedback) override {
+ RTC_DCHECK(network_thread_.CalledOnValidThread());
+ rtc::CritScope lock(&crit_);
+ if (feedback_observer_)
+ feedback_observer_->OnTransportFeedback(feedback);
+ }
+
+ private:
+ rtc::CriticalSection crit_;
+ rtc::ThreadChecker thread_checker_;
+ rtc::ThreadChecker pacer_thread_;
+ rtc::ThreadChecker network_thread_;
+ TransportFeedbackObserver* feedback_observer_ GUARDED_BY(&crit_);
+};
+
+class TransportSequenceNumberProxy : public TransportSequenceNumberAllocator {
+ public:
+ TransportSequenceNumberProxy() : seq_num_allocator_(nullptr) {
+ pacer_thread_.DetachFromThread();
+ }
+
+ void SetSequenceNumberAllocator(
+ TransportSequenceNumberAllocator* seq_num_allocator) {
+ RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ rtc::CritScope lock(&crit_);
+ seq_num_allocator_ = seq_num_allocator;
+ }
+
+ // Implements TransportSequenceNumberAllocator.
+ uint16_t AllocateSequenceNumber() override {
+ RTC_DCHECK(pacer_thread_.CalledOnValidThread());
+ rtc::CritScope lock(&crit_);
+ if (!seq_num_allocator_)
+ return 0;
+ return seq_num_allocator_->AllocateSequenceNumber();
+ }
+
+ private:
+ rtc::CriticalSection crit_;
+ rtc::ThreadChecker thread_checker_;
+ rtc::ThreadChecker pacer_thread_;
+ TransportSequenceNumberAllocator* seq_num_allocator_ GUARDED_BY(&crit_);
+};
+
+class RtpPacketSenderProxy : public RtpPacketSender {
+ public:
+ RtpPacketSenderProxy() : rtp_packet_sender_(nullptr) {
+ }
+
+ void SetPacketSender(RtpPacketSender* rtp_packet_sender) {
+ RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ rtc::CritScope lock(&crit_);
+ rtp_packet_sender_ = rtp_packet_sender;
+ }
+
+ // Implements RtpPacketSender.
+ void InsertPacket(Priority priority,
+ uint32_t ssrc,
+ uint16_t sequence_number,
+ int64_t capture_time_ms,
+ size_t bytes,
+ bool retransmission) override {
+ rtc::CritScope lock(&crit_);
+ if (rtp_packet_sender_) {
+ rtp_packet_sender_->InsertPacket(priority, ssrc, sequence_number,
+ capture_time_ms, bytes, retransmission);
+ }
+ }
+
+ private:
+ rtc::ThreadChecker thread_checker_;
+ rtc::CriticalSection crit_;
+ RtpPacketSender* rtp_packet_sender_ GUARDED_BY(&crit_);
+};
+
// Extend the default RTCP statistics struct with max_jitter, defined as the
// maximum jitter value seen in an RTCP report block.
struct ChannelStatistics : public RtcpStatistics {
@@ -690,89 +790,97 @@
uint32_t instanceId,
RtcEventLog* const event_log,
const Config& config)
- : _fileCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
- _callbackCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
- volume_settings_critsect_(*CriticalSectionWrapper::CreateCriticalSection()),
- _instanceId(instanceId),
- _channelId(channelId),
- event_log_(event_log),
- rtp_header_parser_(RtpHeaderParser::Create()),
- rtp_payload_registry_(
- new RTPPayloadRegistry(RTPPayloadStrategy::CreateStrategy(true))),
- rtp_receive_statistics_(
- ReceiveStatistics::Create(Clock::GetRealTimeClock())),
- rtp_receiver_(
- RtpReceiver::CreateAudioReceiver(Clock::GetRealTimeClock(),
- this,
- this,
- this,
- rtp_payload_registry_.get())),
- telephone_event_handler_(rtp_receiver_->GetTelephoneEventHandler()),
- _outputAudioLevel(),
- _externalTransport(false),
- _inputFilePlayerPtr(NULL),
- _outputFilePlayerPtr(NULL),
- _outputFileRecorderPtr(NULL),
- // Avoid conflict with other channels by adding 1024 - 1026,
- // won't use as much as 1024 channels.
- _inputFilePlayerId(VoEModuleId(instanceId, channelId) + 1024),
- _outputFilePlayerId(VoEModuleId(instanceId, channelId) + 1025),
- _outputFileRecorderId(VoEModuleId(instanceId, channelId) + 1026),
- _outputFileRecording(false),
- _inbandDtmfQueue(VoEModuleId(instanceId, channelId)),
- _inbandDtmfGenerator(VoEModuleId(instanceId, channelId)),
- _outputExternalMedia(false),
- _inputExternalMediaCallbackPtr(NULL),
- _outputExternalMediaCallbackPtr(NULL),
- _timeStamp(0), // This is just an offset, RTP module will add it's own
- // random offset
- _sendTelephoneEventPayloadType(106),
- ntp_estimator_(Clock::GetRealTimeClock()),
- jitter_buffer_playout_timestamp_(0),
- playout_timestamp_rtp_(0),
- playout_timestamp_rtcp_(0),
- playout_delay_ms_(0),
- _numberOfDiscardedPackets(0),
- send_sequence_number_(0),
- ts_stats_lock_(CriticalSectionWrapper::CreateCriticalSection()),
- rtp_ts_wraparound_handler_(new rtc::TimestampWrapAroundHandler()),
- capture_start_rtp_time_stamp_(-1),
- capture_start_ntp_time_ms_(-1),
- _engineStatisticsPtr(NULL),
- _outputMixerPtr(NULL),
- _transmitMixerPtr(NULL),
- _moduleProcessThreadPtr(NULL),
- _audioDeviceModulePtr(NULL),
- _voiceEngineObserverPtr(NULL),
- _callbackCritSectPtr(NULL),
- _transportPtr(NULL),
- _rxVadObserverPtr(NULL),
- _oldVadDecision(-1),
- _sendFrameType(0),
- _externalMixing(false),
- _mixFileWithMicrophone(false),
- _mute(false),
- _panLeft(1.0f),
- _panRight(1.0f),
- _outputGain(1.0f),
- _playOutbandDtmfEvent(false),
- _playInbandDtmfEvent(false),
- _lastLocalTimeStamp(0),
- _lastPayloadType(0),
- _includeAudioLevelIndication(false),
- _outputSpeechType(AudioFrame::kNormalSpeech),
- video_sync_lock_(CriticalSectionWrapper::CreateCriticalSection()),
- _average_jitter_buffer_delay_us(0),
- _previousTimestamp(0),
- _recPacketDelayMs(20),
- _RxVadDetection(false),
- _rxAgcIsEnabled(false),
- _rxNsIsEnabled(false),
- restored_packet_in_use_(false),
- rtcp_observer_(new VoERtcpObserver(this)),
- network_predictor_(new NetworkPredictor(Clock::GetRealTimeClock())),
- assoc_send_channel_lock_(CriticalSectionWrapper::CreateCriticalSection()),
- associate_send_channel_(ChannelOwner(nullptr)) {
+ : _fileCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
+ _callbackCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
+ volume_settings_critsect_(
+ *CriticalSectionWrapper::CreateCriticalSection()),
+ _instanceId(instanceId),
+ _channelId(channelId),
+ event_log_(event_log),
+ rtp_header_parser_(RtpHeaderParser::Create()),
+ rtp_payload_registry_(
+ new RTPPayloadRegistry(RTPPayloadStrategy::CreateStrategy(true))),
+ rtp_receive_statistics_(
+ ReceiveStatistics::Create(Clock::GetRealTimeClock())),
+ rtp_receiver_(
+ RtpReceiver::CreateAudioReceiver(Clock::GetRealTimeClock(),
+ this,
+ this,
+ this,
+ rtp_payload_registry_.get())),
+ telephone_event_handler_(rtp_receiver_->GetTelephoneEventHandler()),
+ _outputAudioLevel(),
+ _externalTransport(false),
+ _inputFilePlayerPtr(NULL),
+ _outputFilePlayerPtr(NULL),
+ _outputFileRecorderPtr(NULL),
+ // Avoid conflict with other channels by adding 1024 - 1026,
+ // won't use as much as 1024 channels.
+ _inputFilePlayerId(VoEModuleId(instanceId, channelId) + 1024),
+ _outputFilePlayerId(VoEModuleId(instanceId, channelId) + 1025),
+ _outputFileRecorderId(VoEModuleId(instanceId, channelId) + 1026),
+ _outputFileRecording(false),
+ _inbandDtmfQueue(VoEModuleId(instanceId, channelId)),
+ _inbandDtmfGenerator(VoEModuleId(instanceId, channelId)),
+ _outputExternalMedia(false),
+ _inputExternalMediaCallbackPtr(NULL),
+ _outputExternalMediaCallbackPtr(NULL),
+ _timeStamp(0), // This is just an offset, RTP module will add it's own
+ // random offset
+ _sendTelephoneEventPayloadType(106),
+ ntp_estimator_(Clock::GetRealTimeClock()),
+ jitter_buffer_playout_timestamp_(0),
+ playout_timestamp_rtp_(0),
+ playout_timestamp_rtcp_(0),
+ playout_delay_ms_(0),
+ _numberOfDiscardedPackets(0),
+ send_sequence_number_(0),
+ ts_stats_lock_(CriticalSectionWrapper::CreateCriticalSection()),
+ rtp_ts_wraparound_handler_(new rtc::TimestampWrapAroundHandler()),
+ capture_start_rtp_time_stamp_(-1),
+ capture_start_ntp_time_ms_(-1),
+ _engineStatisticsPtr(NULL),
+ _outputMixerPtr(NULL),
+ _transmitMixerPtr(NULL),
+ _moduleProcessThreadPtr(NULL),
+ _audioDeviceModulePtr(NULL),
+ _voiceEngineObserverPtr(NULL),
+ _callbackCritSectPtr(NULL),
+ _transportPtr(NULL),
+ _rxVadObserverPtr(NULL),
+ _oldVadDecision(-1),
+ _sendFrameType(0),
+ _externalMixing(false),
+ _mixFileWithMicrophone(false),
+ _mute(false),
+ _panLeft(1.0f),
+ _panRight(1.0f),
+ _outputGain(1.0f),
+ _playOutbandDtmfEvent(false),
+ _playInbandDtmfEvent(false),
+ _lastLocalTimeStamp(0),
+ _lastPayloadType(0),
+ _includeAudioLevelIndication(false),
+ _outputSpeechType(AudioFrame::kNormalSpeech),
+ video_sync_lock_(CriticalSectionWrapper::CreateCriticalSection()),
+ _average_jitter_buffer_delay_us(0),
+ _previousTimestamp(0),
+ _recPacketDelayMs(20),
+ _RxVadDetection(false),
+ _rxAgcIsEnabled(false),
+ _rxNsIsEnabled(false),
+ restored_packet_in_use_(false),
+ rtcp_observer_(new VoERtcpObserver(this)),
+ network_predictor_(new NetworkPredictor(Clock::GetRealTimeClock())),
+ assoc_send_channel_lock_(CriticalSectionWrapper::CreateCriticalSection()),
+ associate_send_channel_(ChannelOwner(nullptr)),
+ pacing_enabled_(config.Get<VoicePacing>().enabled),
+ feedback_observer_proxy_(pacing_enabled_ ? new TransportFeedbackProxy()
+ : nullptr),
+ seq_num_allocator_proxy_(
+ pacing_enabled_ ? new TransportSequenceNumberProxy() : nullptr),
+ rtp_packet_sender_proxy_(pacing_enabled_ ? new RtpPacketSenderProxy()
+ : nullptr) {
WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId),
"Channel::Channel() - ctor");
AudioCodingModule::Config acm_config;
@@ -797,6 +905,10 @@
configuration.audio_messages = this;
configuration.receive_statistics = rtp_receive_statistics_.get();
configuration.bandwidth_callback = rtcp_observer_.get();
+ configuration.paced_sender = rtp_packet_sender_proxy_.get();
+ configuration.transport_sequence_number_allocator =
+ seq_num_allocator_proxy_.get();
+ configuration.transport_feedback_callback = feedback_observer_proxy_.get();
_rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration));
@@ -2787,6 +2899,33 @@
return 0;
}
+void Channel::EnableSendTransportSequenceNumber(int id) {
+ int ret =
+ SetSendRtpHeaderExtension(true, kRtpExtensionTransportSequenceNumber, id);
+ RTC_DCHECK_EQ(0, ret);
+}
+
+void Channel::SetCongestionControlObjects(
+ RtpPacketSender* rtp_packet_sender,
+ TransportFeedbackObserver* transport_feedback_observer,
+ PacketRouter* packet_router) {
+ RTC_DCHECK(feedback_observer_proxy_.get());
+ RTC_DCHECK(seq_num_allocator_proxy_.get());
+ RTC_DCHECK(rtp_packet_sender_proxy_.get());
+ RTC_DCHECK(packet_router != nullptr || packet_router_ != nullptr);
+ feedback_observer_proxy_->SetTransportFeedbackObserver(
+ transport_feedback_observer);
+ seq_num_allocator_proxy_->SetSequenceNumberAllocator(packet_router);
+ rtp_packet_sender_proxy_->SetPacketSender(rtp_packet_sender);
+ _rtpRtcpModule->SetStorePacketsStatus(rtp_packet_sender != nullptr, 600);
+ if (packet_router != nullptr) {
+ packet_router->AddRtpModule(_rtpRtcpModule.get());
+ } else {
+ packet_router_->RemoveRtpModule(_rtpRtcpModule.get());
+ }
+ packet_router_ = packet_router;
+}
+
void Channel::SetRTCPStatus(bool enable) {
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::SetRTCPStatus()");
@@ -3165,7 +3304,9 @@
void Channel::SetNACKStatus(bool enable, int maxNumberOfPackets) {
// None of these functions can fail.
- _rtpRtcpModule->SetStorePacketsStatus(enable, maxNumberOfPackets);
+ // If pacing is enabled we always store packets.
+ if (!pacing_enabled_)
+ _rtpRtcpModule->SetStorePacketsStatus(enable, maxNumberOfPackets);
rtp_receive_statistics_->SetMaxReorderingThreshold(maxNumberOfPackets);
rtp_receiver_->SetNACKStatus(enable ? kNackRtcp : kNackOff);
if (enable)
diff --git a/voice_engine/channel.h b/voice_engine/channel.h
index f26fdb2..d3b1b93 100644
--- a/voice_engine/channel.h
+++ b/voice_engine/channel.h
@@ -11,13 +11,13 @@
#ifndef WEBRTC_VOICE_ENGINE_CHANNEL_H_
#define WEBRTC_VOICE_ENGINE_CHANNEL_H_
+#include "webrtc/base/criticalsection.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/common_audio/resampler/include/push_resampler.h"
#include "webrtc/common_types.h"
#include "webrtc/modules/audio_coding/include/audio_coding_module.h"
#include "webrtc/modules/audio_conference_mixer/include/audio_conference_mixer_defines.h"
#include "webrtc/modules/audio_processing/rms_level.h"
-#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
#include "webrtc/modules/rtp_rtcp/include/remote_ntp_time_estimator.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
@@ -48,6 +48,7 @@
class Config;
class CriticalSectionWrapper;
class FileWrapper;
+class PacketRouter;
class ProcessThread;
class ReceiveStatistics;
class RemoteNtpTimeEstimator;
@@ -68,9 +69,12 @@
namespace voe {
class OutputMixer;
+class RtpPacketSenderProxy;
class Statistics;
class StatisticsProxy;
+class TransportFeedbackProxy;
class TransmitMixer;
+class TransportSequenceNumberProxy;
class VoERtcpObserver;
// Helper class to simplify locking scheme for members that are accessed from
@@ -321,6 +325,13 @@
int SetReceiveAudioLevelIndicationStatus(bool enable, unsigned char id);
int SetSendAbsoluteSenderTimeStatus(bool enable, unsigned char id);
int SetReceiveAbsoluteSenderTimeStatus(bool enable, unsigned char id);
+ void EnableSendTransportSequenceNumber(int id);
+
+ void SetCongestionControlObjects(
+ RtpPacketSender* rtp_packet_sender,
+ TransportFeedbackObserver* transport_feedback_observer,
+ PacketRouter* packet_router);
+
void SetRTCPStatus(bool enable);
int GetRTCPStatus(bool& enabled);
int SetRTCP_CNAME(const char cName[256]);
@@ -584,6 +595,12 @@
// An associated send channel.
rtc::scoped_ptr<CriticalSectionWrapper> assoc_send_channel_lock_;
ChannelOwner associate_send_channel_ GUARDED_BY(assoc_send_channel_lock_);
+
+ bool pacing_enabled_;
+ PacketRouter* packet_router_ = nullptr;
+ rtc::scoped_ptr<TransportFeedbackProxy> feedback_observer_proxy_;
+ rtc::scoped_ptr<TransportSequenceNumberProxy> seq_num_allocator_proxy_;
+ rtc::scoped_ptr<RtpPacketSenderProxy> rtp_packet_sender_proxy_;
};
} // namespace voe
diff --git a/voice_engine/channel_proxy.cc b/voice_engine/channel_proxy.cc
index 1772ad5..68fbf38 100644
--- a/voice_engine/channel_proxy.cc
+++ b/voice_engine/channel_proxy.cc
@@ -52,6 +52,11 @@
RTC_DCHECK_EQ(0, error);
}
+void ChannelProxy::EnableSendTransportSequenceNumber(int id) {
+ RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ channel()->EnableSendTransportSequenceNumber(id);
+}
+
void ChannelProxy::SetReceiveAbsoluteSenderTimeStatus(bool enable, int id) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
int error = channel()->SetReceiveAbsoluteSenderTimeStatus(enable, id);
@@ -64,6 +69,15 @@
RTC_DCHECK_EQ(0, error);
}
+void ChannelProxy::SetCongestionControlObjects(
+ RtpPacketSender* rtp_packet_sender,
+ TransportFeedbackObserver* transport_feedback_observer,
+ PacketRouter* packet_router) {
+ RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ channel()->SetCongestionControlObjects(
+ rtp_packet_sender, transport_feedback_observer, packet_router);
+}
+
CallStatistics ChannelProxy::GetRTCPStatistics() const {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
CallStatistics stats = {0};
@@ -124,5 +138,6 @@
RTC_DCHECK(channel_owner_.channel());
return channel_owner_.channel();
}
+
} // namespace voe
} // namespace webrtc
diff --git a/voice_engine/channel_proxy.h b/voice_engine/channel_proxy.h
index 3668de4..fa33e6c 100644
--- a/voice_engine/channel_proxy.h
+++ b/voice_engine/channel_proxy.h
@@ -19,6 +19,11 @@
#include <vector>
namespace webrtc {
+
+class PacketRouter;
+class RtpPacketSender;
+class TransportFeedbackObserver;
+
namespace voe {
class Channel;
@@ -41,8 +46,13 @@
virtual void SetRTCP_CNAME(const std::string& c_name);
virtual void SetSendAbsoluteSenderTimeStatus(bool enable, int id);
virtual void SetSendAudioLevelIndicationStatus(bool enable, int id);
+ virtual void EnableSendTransportSequenceNumber(int id);
virtual void SetReceiveAbsoluteSenderTimeStatus(bool enable, int id);
virtual void SetReceiveAudioLevelIndicationStatus(bool enable, int id);
+ virtual void SetCongestionControlObjects(
+ RtpPacketSender* rtp_packet_sender,
+ TransportFeedbackObserver* transport_feedback_observer,
+ PacketRouter* packet_router);
virtual CallStatistics GetRTCPStatistics() const;
virtual std::vector<ReportBlock> GetRemoteRTCPReportBlocks() const;
diff --git a/voice_engine/voice_engine.gyp b/voice_engine/voice_engine.gyp
index c9b0d85..ff588d8 100644
--- a/voice_engine/voice_engine.gyp
+++ b/voice_engine/voice_engine.gyp
@@ -23,6 +23,7 @@
'<(webrtc_root)/modules/modules.gyp:audio_processing',
'<(webrtc_root)/modules/modules.gyp:bitrate_controller',
'<(webrtc_root)/modules/modules.gyp:media_file',
+ '<(webrtc_root)/modules/modules.gyp:paced_sender',
'<(webrtc_root)/modules/modules.gyp:rtp_rtcp',
'<(webrtc_root)/modules/modules.gyp:webrtc_utility',
'<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers',