Move some send stream configuration into webrtc::AudioSendStream.
BUG=webrtc:4690
Review URL: https://codereview.webrtc.org/1418503010
Cr-Commit-Position: refs/heads/master@{#10652}
diff --git a/talk/media/webrtc/fakewebrtcvoiceengine.h b/talk/media/webrtc/fakewebrtcvoiceengine.h
index d031d10..8ef57d3 100644
--- a/talk/media/webrtc/fakewebrtcvoiceengine.h
+++ b/talk/media/webrtc/fakewebrtcvoiceengine.h
@@ -188,9 +188,7 @@
red_type(117),
nack_max_packets(0),
send_ssrc(0),
- send_audio_level_ext_(-1),
receive_audio_level_ext_(-1),
- send_absolute_sender_time_ext_(-1),
receive_absolute_sender_time_ext_(-1),
associate_send_channel(-1),
neteq_capacity(-1),
@@ -213,9 +211,7 @@
int red_type;
int nack_max_packets;
uint32_t send_ssrc;
- int send_audio_level_ext_;
int receive_audio_level_ext_;
- int send_absolute_sender_time_ext_;
int receive_absolute_sender_time_ext_;
int associate_send_channel;
DtmfInfo dtmf_info;
@@ -267,14 +263,6 @@
bool IsInited() const { return inited_; }
int GetLastChannel() const { return last_channel_; }
- int GetChannelFromLocalSsrc(uint32_t local_ssrc) const {
- for (std::map<int, Channel*>::const_iterator iter = channels_.begin();
- iter != channels_.end(); ++iter) {
- if (local_ssrc == iter->second->send_ssrc)
- return iter->first;
- }
- return -1;
- }
int GetNumChannels() const { return static_cast<int>(channels_.size()); }
uint32_t GetLocalSSRC(int channel) {
return channels_[channel]->send_ssrc;
@@ -364,15 +352,6 @@
channels_[++last_channel_] = ch;
return last_channel_;
}
- int GetSendRtpExtensionId(int channel, const std::string& extension) {
- WEBRTC_ASSERT_CHANNEL(channel);
- if (extension == kRtpAudioLevelHeaderExtension) {
- return channels_[channel]->send_audio_level_ext_;
- } else if (extension == kRtpAbsoluteSenderTimeHeaderExtension) {
- return channels_[channel]->send_absolute_sender_time_ext_;
- }
- return -1;
- }
int GetReceiveRtpExtensionId(int channel, const std::string& extension) {
WEBRTC_ASSERT_CHANNEL(channel);
if (extension == kRtpAudioLevelHeaderExtension) {
@@ -729,13 +708,8 @@
}
WEBRTC_STUB(GetLocalSSRC, (int channel, unsigned int& ssrc));
WEBRTC_STUB(GetRemoteSSRC, (int channel, unsigned int& ssrc));
- WEBRTC_FUNC(SetSendAudioLevelIndicationStatus, (int channel, bool enable,
- unsigned char id)) {
- WEBRTC_CHECK_CHANNEL(channel);
- WEBRTC_CHECK_HEADER_EXTENSION_ID(enable, id);
- channels_[channel]->send_audio_level_ext_ = (enable) ? id : -1;
- return 0;
- }
+ WEBRTC_STUB(SetSendAudioLevelIndicationStatus, (int channel, bool enable,
+ unsigned char id));
WEBRTC_FUNC(SetReceiveAudioLevelIndicationStatus, (int channel, bool enable,
unsigned char id)) {
WEBRTC_CHECK_CHANNEL(channel);
@@ -743,13 +717,8 @@
channels_[channel]->receive_audio_level_ext_ = (enable) ? id : -1;
return 0;
}
- WEBRTC_FUNC(SetSendAbsoluteSenderTimeStatus, (int channel, bool enable,
- unsigned char id)) {
- WEBRTC_CHECK_CHANNEL(channel);
- WEBRTC_CHECK_HEADER_EXTENSION_ID(enable, id);
- channels_[channel]->send_absolute_sender_time_ext_ = (enable) ? id : -1;
- return 0;
- }
+ WEBRTC_STUB(SetSendAbsoluteSenderTimeStatus, (int channel, bool enable,
+ unsigned char id));
WEBRTC_FUNC(SetReceiveAbsoluteSenderTimeStatus, (int channel, bool enable,
unsigned char id)) {
WEBRTC_CHECK_CHANNEL(channel);
diff --git a/talk/media/webrtc/webrtcvoiceengine.cc b/talk/media/webrtc/webrtcvoiceengine.cc
index a7e1a43..c13b229 100644
--- a/talk/media/webrtc/webrtcvoiceengine.cc
+++ b/talk/media/webrtc/webrtcvoiceengine.cc
@@ -396,6 +396,19 @@
return config;
}
+std::vector<webrtc::RtpExtension> FindAudioRtpHeaderExtensions(
+ const std::vector<RtpHeaderExtension>& extensions) {
+ std::vector<webrtc::RtpExtension> result;
+ for (const auto& extension : extensions) {
+ if (extension.uri == kRtpAbsoluteSenderTimeHeaderExtension ||
+ extension.uri == kRtpAudioLevelHeaderExtension) {
+ result.push_back({extension.uri, extension.id});
+ } else {
+ LOG(LS_WARNING) << "Unsupported RTP extension: " << extension.ToString();
+ }
+ }
+ return result;
+}
} // namespace {
WebRtcVoiceEngine::WebRtcVoiceEngine()
@@ -1337,27 +1350,49 @@
: public AudioRenderer::Sink {
public:
WebRtcAudioSendStream(int ch, webrtc::AudioTransport* voe_audio_transport,
- uint32_t ssrc, webrtc::Call* call)
+ uint32_t ssrc, const std::string& c_name,
+ const std::vector<webrtc::RtpExtension>& extensions,
+ webrtc::Call* call)
: channel_(ch),
voe_audio_transport_(voe_audio_transport),
- call_(call) {
+ call_(call),
+ config_(nullptr) {
RTC_DCHECK_GE(ch, 0);
// TODO(solenberg): Once we're not using FakeWebRtcVoiceEngine anymore:
// RTC_DCHECK(voe_audio_transport);
RTC_DCHECK(call);
audio_capture_thread_checker_.DetachFromThread();
- webrtc::AudioSendStream::Config config(nullptr);
- config.voe_channel_id = channel_;
- config.rtp.ssrc = ssrc;
- stream_ = call_->CreateAudioSendStream(config);
- RTC_DCHECK(stream_);
+ config_.rtp.ssrc = ssrc;
+ config_.rtp.c_name = c_name;
+ config_.voe_channel_id = ch;
+ RecreateAudioSendStream(extensions);
}
+
~WebRtcAudioSendStream() override {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Stop();
call_->DestroyAudioSendStream(stream_);
}
+ void RecreateAudioSendStream(
+ const std::vector<webrtc::RtpExtension>& extensions) {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ if (stream_) {
+ call_->DestroyAudioSendStream(stream_);
+ stream_ = nullptr;
+ }
+ config_.rtp.extensions = extensions;
+ RTC_DCHECK(!stream_);
+ stream_ = call_->CreateAudioSendStream(config_);
+ RTC_CHECK(stream_);
+ }
+
+ webrtc::AudioSendStream::Stats GetStats() const {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(stream_);
+ return stream_->GetStats();
+ }
+
// Starts the rendering by setting a sink to the renderer to get data
// callback.
// This method is called on the libjingle worker thread.
@@ -1373,11 +1408,6 @@
renderer_ = renderer;
}
- webrtc::AudioSendStream::Stats GetStats() const {
- RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
- return stream_->GetStats();
- }
-
// Stops rendering by setting the sink of the renderer to nullptr. No data
// callback will be received after this method.
// This method is called on the libjingle worker thread.
@@ -1428,6 +1458,9 @@
const int channel_ = -1;
webrtc::AudioTransport* const voe_audio_transport_ = nullptr;
webrtc::Call* call_ = nullptr;
+ webrtc::AudioSendStream::Config config_;
+ // The stream is owned by WebRtcAudioSendStream and may be reallocated if
+ // configuration changes.
webrtc::AudioSendStream* stream_ = nullptr;
// Raw pointer to AudioRenderer owned by LocalAudioTrackHandler.
@@ -1486,10 +1519,24 @@
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
// TODO(pthatcher): Refactor this to be more clean now that we have
// all the information at once.
- return (SetSendCodecs(params.codecs) &&
- SetSendRtpHeaderExtensions(params.extensions) &&
- SetMaxSendBandwidth(params.max_bandwidth_bps) &&
- SetOptions(params.options));
+
+ if (!SetSendCodecs(params.codecs)) {
+ return false;
+ }
+
+ std::vector<webrtc::RtpExtension> send_rtp_extensions =
+ FindAudioRtpHeaderExtensions(params.extensions);
+ if (send_rtp_extensions_ != send_rtp_extensions) {
+ send_rtp_extensions_.swap(send_rtp_extensions);
+ for (auto& it : send_streams_) {
+ it.second->RecreateAudioSendStream(send_rtp_extensions_);
+ }
+ }
+
+ if (!SetMaxSendBandwidth(params.max_bandwidth_bps)) {
+ return false;
+ }
+ return SetOptions(params.options);
}
bool WebRtcVoiceMediaChannel::SetRecvParameters(
@@ -1870,26 +1917,8 @@
receive_extensions_ = extensions;
// Recreate AudioReceiveStream:s.
- {
- std::vector<webrtc::RtpExtension> exts;
-
- const RtpHeaderExtension* audio_level_extension =
- FindHeaderExtension(extensions, kRtpAudioLevelHeaderExtension);
- if (audio_level_extension) {
- exts.push_back({
- kRtpAudioLevelHeaderExtension, audio_level_extension->id});
- }
-
- const RtpHeaderExtension* send_time_extension =
- FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension);
- if (send_time_extension) {
- exts.push_back({
- kRtpAbsoluteSenderTimeHeaderExtension, send_time_extension->id});
- }
-
- recv_rtp_extensions_.swap(exts);
- RecreateAudioReceiveStreams();
- }
+ recv_rtp_extensions_ = FindAudioRtpHeaderExtensions(extensions);
+ RecreateAudioReceiveStreams();
return true;
}
@@ -1915,45 +1944,6 @@
return true;
}
-bool WebRtcVoiceMediaChannel::SetSendRtpHeaderExtensions(
- const std::vector<RtpHeaderExtension>& extensions) {
- RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
- if (send_extensions_ == extensions) {
- return true;
- }
-
- for (const auto& ch : send_streams_) {
- if (!SetChannelSendRtpHeaderExtensions(ch.second->channel(), extensions)) {
- return false;
- }
- }
-
- send_extensions_ = extensions;
- return true;
-}
-
-bool WebRtcVoiceMediaChannel::SetChannelSendRtpHeaderExtensions(
- int channel_id, const std::vector<RtpHeaderExtension>& extensions) {
- const RtpHeaderExtension* audio_level_extension =
- FindHeaderExtension(extensions, kRtpAudioLevelHeaderExtension);
-
- if (!SetHeaderExtension(
- &webrtc::VoERTP_RTCP::SetSendAudioLevelIndicationStatus, channel_id,
- audio_level_extension)) {
- return false;
- }
-
- const RtpHeaderExtension* send_time_extension =
- FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension);
- if (!SetHeaderExtension(
- &webrtc::VoERTP_RTCP::SetSendAbsoluteSenderTimeStatus, channel_id,
- send_time_extension)) {
- return false;
- }
-
- return true;
-}
-
bool WebRtcVoiceMediaChannel::SetPlayout(bool playout) {
desired_playout_ = playout;
return ChangePlayout(desired_playout_);
@@ -2107,33 +2097,12 @@
return false;
}
- // Enable RTCP (for quality stats and feedback messages).
- if (engine()->voe()->rtp()->SetRTCPStatus(channel, true) == -1) {
- LOG_RTCERR2(SetRTCPStatus, channel, 1);
- }
-
- SetChannelSendRtpHeaderExtensions(channel, send_extensions_);
-
- // Set the local (send) SSRC.
- if (engine()->voe()->rtp()->SetLocalSSRC(channel, ssrc) == -1) {
- LOG_RTCERR2(SetLocalSSRC, channel, ssrc);
- DeleteChannel(channel);
- return false;
- }
-
- if (engine()->voe()->rtp()->SetRTCP_CNAME(channel, sp.cname.c_str()) == -1) {
- LOG_RTCERR2(SetRTCP_CNAME, channel, sp.cname);
- DeleteChannel(channel);
- return false;
- }
-
// Save the channel to send_streams_, so that RemoveSendStream() can still
// delete the channel in case failure happens below.
webrtc::AudioTransport* audio_transport =
engine()->voe()->base()->audio_transport();
- send_streams_.insert(
- std::make_pair(ssrc,
- new WebRtcAudioSendStream(channel, audio_transport, ssrc, call_)));
+ send_streams_.insert(std::make_pair(ssrc, new WebRtcAudioSendStream(
+ channel, audio_transport, ssrc, sp.cname, send_rtp_extensions_, call_)));
// Set the current codecs to be used for the new channel. We need to do this
// after adding the channel to send_channels_, because of how max bitrate is
@@ -2165,6 +2134,8 @@
bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ LOG(LS_INFO) << "RemoveSendStream: " << ssrc;
+
auto it = send_streams_.find(ssrc);
if (it == send_streams_.end()) {
LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
diff --git a/talk/media/webrtc/webrtcvoiceengine.h b/talk/media/webrtc/webrtcvoiceengine.h
index e480c13..2f74dab 100644
--- a/talk/media/webrtc/webrtcvoiceengine.h
+++ b/talk/media/webrtc/webrtcvoiceengine.h
@@ -245,8 +245,6 @@
private:
bool SetSendCodecs(const std::vector<AudioCodec>& codecs);
- bool SetSendRtpHeaderExtensions(
- const std::vector<RtpHeaderExtension>& extensions);
bool SetOptions(const AudioOptions& options);
bool SetMaxSendBandwidth(int bps);
bool SetRecvCodecs(const std::vector<AudioCodec>& codecs);
@@ -290,9 +288,6 @@
bool SetChannelRecvRtpHeaderExtensions(
int channel_id,
const std::vector<RtpHeaderExtension>& extensions);
- bool SetChannelSendRtpHeaderExtensions(
- int channel_id,
- const std::vector<RtpHeaderExtension>& extensions);
rtc::ThreadChecker worker_thread_checker_;
@@ -322,7 +317,7 @@
class WebRtcAudioSendStream;
std::map<uint32_t, WebRtcAudioSendStream*> send_streams_;
- std::vector<RtpHeaderExtension> send_extensions_;
+ std::vector<webrtc::RtpExtension> send_rtp_extensions_;
class WebRtcAudioReceiveStream;
std::map<uint32_t, WebRtcAudioReceiveStream*> receive_channels_;
diff --git a/talk/media/webrtc/webrtcvoiceengine_unittest.cc b/talk/media/webrtc/webrtcvoiceengine_unittest.cc
index 0e2781b..b123a84 100644
--- a/talk/media/webrtc/webrtcvoiceengine_unittest.cc
+++ b/talk/media/webrtc/webrtcvoiceengine_unittest.cc
@@ -124,12 +124,10 @@
void SetupForMultiSendStream() {
EXPECT_TRUE(SetupEngineWithSendStream());
// Remove stream added in Setup.
- int default_channel_num = voe_.GetLastChannel();
- EXPECT_EQ(kSsrc1, voe_.GetLocalSSRC(default_channel_num));
+ EXPECT_TRUE(call_.GetAudioSendStream(kSsrc1));
EXPECT_TRUE(channel_->RemoveSendStream(kSsrc1));
-
// Verify the channel does not exist.
- EXPECT_EQ(-1, voe_.GetChannelFromLocalSsrc(kSsrc1));
+ EXPECT_FALSE(call_.GetAudioSendStream(kSsrc1));
}
void DeliverPacket(const void* data, int len) {
rtc::Buffer packet(reinterpret_cast<const uint8_t*>(data), len);
@@ -140,6 +138,12 @@
engine_.Terminate();
}
+ const webrtc::AudioSendStream::Config& GetSendStreamConfig(uint32_t ssrc) {
+ const auto* send_stream = call_.GetAudioSendStream(ssrc);
+ EXPECT_TRUE(send_stream);
+ return send_stream->GetConfig();
+ }
+
void TestInsertDtmf(uint32_t ssrc, bool caller) {
EXPECT_TRUE(engine_.Init(rtc::Thread::Current()));
channel_ = engine_.CreateChannel(&call_, cricket::AudioOptions());
@@ -212,41 +216,44 @@
void TestSetSendRtpHeaderExtensions(const std::string& ext) {
EXPECT_TRUE(SetupEngineWithSendStream());
- int channel_num = voe_.GetLastChannel();
// Ensure extensions are off by default.
- EXPECT_EQ(-1, voe_.GetSendRtpExtensionId(channel_num, ext));
+ EXPECT_EQ(0u, GetSendStreamConfig(kSsrc1).rtp.extensions.size());
// Ensure unknown extensions won't cause an error.
send_parameters_.extensions.push_back(cricket::RtpHeaderExtension(
"urn:ietf:params:unknownextention", 1));
EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
- EXPECT_EQ(-1, voe_.GetSendRtpExtensionId(channel_num, ext));
+ EXPECT_EQ(0u, GetSendStreamConfig(kSsrc1).rtp.extensions.size());
// Ensure extensions stay off with an empty list of headers.
send_parameters_.extensions.clear();
EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
- EXPECT_EQ(-1, voe_.GetSendRtpExtensionId(channel_num, ext));
+ EXPECT_EQ(0u, GetSendStreamConfig(kSsrc1).rtp.extensions.size());
// Ensure extension is set properly.
const int id = 1;
send_parameters_.extensions.push_back(cricket::RtpHeaderExtension(ext, id));
EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
- EXPECT_EQ(id, voe_.GetSendRtpExtensionId(channel_num, ext));
+ EXPECT_EQ(1u, GetSendStreamConfig(kSsrc1).rtp.extensions.size());
+ EXPECT_EQ(ext, GetSendStreamConfig(kSsrc1).rtp.extensions[0].name);
+ EXPECT_EQ(id, GetSendStreamConfig(kSsrc1).rtp.extensions[0].id);
// Ensure extension is set properly on new channels.
EXPECT_TRUE(channel_->AddSendStream(
cricket::StreamParams::CreateLegacy(kSsrc2)));
- int new_channel_num = voe_.GetLastChannel();
- EXPECT_NE(channel_num, new_channel_num);
- EXPECT_EQ(id, voe_.GetSendRtpExtensionId(new_channel_num, ext));
+ EXPECT_NE(call_.GetAudioSendStream(kSsrc1),
+ call_.GetAudioSendStream(kSsrc2));
+ EXPECT_EQ(1u, GetSendStreamConfig(kSsrc2).rtp.extensions.size());
+ EXPECT_EQ(ext, GetSendStreamConfig(kSsrc2).rtp.extensions[0].name);
+ EXPECT_EQ(id, GetSendStreamConfig(kSsrc2).rtp.extensions[0].id);
// Ensure all extensions go back off with an empty list.
send_parameters_.codecs.push_back(kPcmuCodec);
send_parameters_.extensions.clear();
EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
- EXPECT_EQ(-1, voe_.GetSendRtpExtensionId(channel_num, ext));
- EXPECT_EQ(-1, voe_.GetSendRtpExtensionId(new_channel_num, ext));
+ EXPECT_EQ(0u, GetSendStreamConfig(kSsrc1).rtp.extensions.size());
+ EXPECT_EQ(0u, GetSendStreamConfig(kSsrc2).rtp.extensions.size());
}
void TestSetRecvRtpHeaderExtensions(const std::string& ext) {
@@ -1976,21 +1983,16 @@
for (uint32_t ssrc : kSsrcs4) {
EXPECT_TRUE(channel_->AddSendStream(
cricket::StreamParams::CreateLegacy(ssrc)));
- EXPECT_NE(nullptr, call_.GetAudioSendStream(ssrc));
-
// Verify that we are in a sending state for all the created streams.
- int channel_num = voe_.GetChannelFromLocalSsrc(ssrc);
- EXPECT_TRUE(voe_.GetSend(channel_num));
+ EXPECT_TRUE(voe_.GetSend(GetSendStreamConfig(ssrc).voe_channel_id));
}
EXPECT_EQ(arraysize(kSsrcs4), call_.GetAudioSendStreams().size());
// Delete the send streams.
for (uint32_t ssrc : kSsrcs4) {
EXPECT_TRUE(channel_->RemoveSendStream(ssrc));
- EXPECT_EQ(nullptr, call_.GetAudioSendStream(ssrc));
- // Stream should already be deleted.
+ EXPECT_FALSE(call_.GetAudioSendStream(ssrc));
EXPECT_FALSE(channel_->RemoveSendStream(ssrc));
- EXPECT_EQ(-1, voe_.GetChannelFromLocalSsrc(ssrc));
}
EXPECT_EQ(0u, call_.GetAudioSendStreams().size());
}
@@ -2015,7 +2017,7 @@
// Verify ISAC and VAD are corrected configured on all send channels.
webrtc::CodecInst gcodec;
for (uint32_t ssrc : kSsrcs4) {
- int channel_num = voe_.GetChannelFromLocalSsrc(ssrc);
+ int channel_num = GetSendStreamConfig(ssrc).voe_channel_id;
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
EXPECT_STREQ("ISAC", gcodec.plname);
EXPECT_TRUE(voe_.GetVAD(channel_num));
@@ -2026,7 +2028,7 @@
parameters.codecs[0] = kPcmuCodec;
EXPECT_TRUE(channel_->SetSendParameters(parameters));
for (uint32_t ssrc : kSsrcs4) {
- int channel_num = voe_.GetChannelFromLocalSsrc(ssrc);
+ int channel_num = GetSendStreamConfig(ssrc).voe_channel_id;
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
EXPECT_STREQ("PCMU", gcodec.plname);
EXPECT_FALSE(voe_.GetVAD(channel_num));
@@ -2049,7 +2051,7 @@
EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
for (uint32_t ssrc : kSsrcs4) {
// Verify that we are in a sending state for all the send streams.
- int channel_num = voe_.GetChannelFromLocalSsrc(ssrc);
+ int channel_num = GetSendStreamConfig(ssrc).voe_channel_id;
EXPECT_TRUE(voe_.GetSend(channel_num));
}
@@ -2057,7 +2059,7 @@
EXPECT_TRUE(channel_->SetSend(cricket::SEND_NOTHING));
for (uint32_t ssrc : kSsrcs4) {
// Verify that we are in a stop state for all the send streams.
- int channel_num = voe_.GetChannelFromLocalSsrc(ssrc);
+ int channel_num = GetSendStreamConfig(ssrc).voe_channel_id;
EXPECT_FALSE(voe_.GetSend(channel_num));
}
}
@@ -2338,7 +2340,7 @@
// SSRC is set in SetupEngine by calling AddSendStream.
TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrc) {
EXPECT_TRUE(SetupEngineWithSendStream());
- EXPECT_EQ(kSsrc1, voe_.GetLocalSSRC(voe_.GetLastChannel()));
+ EXPECT_TRUE(call_.GetAudioSendStream(kSsrc1));
}
TEST_F(WebRtcVoiceEngineTestFake, GetStats) {
@@ -2399,7 +2401,7 @@
// SSRC is set in SetupEngine by calling AddSendStream.
TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrcWithMultipleStreams) {
EXPECT_TRUE(SetupEngineWithSendStream());
- EXPECT_EQ(kSsrc1, voe_.GetLocalSSRC(voe_.GetLastChannel()));
+ EXPECT_TRUE(call_.GetAudioSendStream(kSsrc1));
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
EXPECT_EQ(kSsrc1, voe_.GetLocalSSRC(voe_.GetLastChannel()));
}
@@ -2414,9 +2416,8 @@
int receive_channel_num = voe_.GetLastChannel();
EXPECT_TRUE(channel_->AddSendStream(
cricket::StreamParams::CreateLegacy(1234)));
- int send_channel_num = voe_.GetLastChannel();
- EXPECT_EQ(1234U, voe_.GetLocalSSRC(send_channel_num));
+ EXPECT_TRUE(call_.GetAudioSendStream(1234));
EXPECT_EQ(1234U, voe_.GetLocalSSRC(receive_channel_num));
}
@@ -3053,6 +3054,8 @@
EXPECT_EQ(arraysize(kSsrcs), call_.GetAudioReceiveStreams().size());
}
+// TODO(solenberg): Remove, once recv streams are configured through Call.
+// (This is then covered by TestSetRecvRtpHeaderExtensions.)
TEST_F(WebRtcVoiceEngineTestFake, ConfiguresAudioReceiveStreamRtpExtensions) {
// Test that setting the header extensions results in the expected state
// changes on an associated Call.
diff --git a/webrtc/audio/audio_receive_stream_unittest.cc b/webrtc/audio/audio_receive_stream_unittest.cc
index 755d634..edd804f 100644
--- a/webrtc/audio/audio_receive_stream_unittest.cc
+++ b/webrtc/audio/audio_receive_stream_unittest.cc
@@ -20,6 +20,9 @@
namespace test {
namespace {
+using testing::_;
+using testing::Return;
+
AudioDecodingCallStats MakeAudioDecodeStatsForTest() {
AudioDecodingCallStats audio_decode_stats;
audio_decode_stats.calls_to_silence_generator = 234;
@@ -50,9 +53,9 @@
struct ConfigHelper {
ConfigHelper() {
EXPECT_CALL(voice_engine_,
- RegisterVoiceEngineObserver(testing::_)).WillOnce(testing::Return(0));
+ RegisterVoiceEngineObserver(_)).WillOnce(Return(0));
EXPECT_CALL(voice_engine_,
- DeRegisterVoiceEngineObserver()).WillOnce(testing::Return(0));
+ DeRegisterVoiceEngineObserver()).WillOnce(Return(0));
AudioState::Config config;
config.voice_engine = &voice_engine_;
audio_state_ = AudioState::Create(config);
@@ -69,9 +72,7 @@
MockVoiceEngine& voice_engine() { return voice_engine_; }
void SetupMockForGetStats() {
- using testing::_;
using testing::DoAll;
- using testing::Return;
using testing::SetArgPointee;
using testing::SetArgReferee;
EXPECT_CALL(voice_engine_, GetRemoteSSRC(kChannelId, _))
@@ -94,7 +95,7 @@
private:
MockRemoteBitrateEstimator remote_bitrate_estimator_;
- MockVoiceEngine voice_engine_;
+ testing::StrictMock<MockVoiceEngine> voice_engine_;
rtc::scoped_refptr<AudioState> audio_state_;
AudioReceiveStream::Config stream_config_;
};
diff --git a/webrtc/audio/audio_send_stream.cc b/webrtc/audio/audio_send_stream.cc
index da24249..14112de 100644
--- a/webrtc/audio/audio_send_stream.cc
+++ b/webrtc/audio/audio_send_stream.cc
@@ -34,6 +34,7 @@
}
}
ss << ']';
+ ss << ", c_name: " << c_name;
ss << '}';
return ss.str();
}
@@ -58,6 +59,31 @@
LOG(LS_INFO) << "AudioSendStream: " << config_.ToString();
RTC_DCHECK_NE(config_.voe_channel_id, -1);
RTC_DCHECK(audio_state_.get());
+
+ const int channel_id = config.voe_channel_id;
+ ScopedVoEInterface<VoERTP_RTCP> rtp(voice_engine());
+ int error = rtp->SetRTCPStatus(channel_id, true);
+ RTC_DCHECK_EQ(0, error);
+ error = rtp->SetLocalSSRC(channel_id, config.rtp.ssrc);
+ RTC_DCHECK_EQ(0, error);
+ error = rtp->SetRTCP_CNAME(channel_id, config.rtp.c_name.c_str());
+ RTC_DCHECK_EQ(0, error);
+ for (const auto& extension : config.rtp.extensions) {
+ // One-byte-extension local identifiers are in the range 1-14 inclusive.
+ RTC_DCHECK_GE(extension.id, 1);
+ RTC_DCHECK_LE(extension.id, 14);
+ if (extension.name == RtpExtension::kAbsSendTime) {
+ error = rtp->SetSendAbsoluteSenderTimeStatus(channel_id, true,
+ extension.id);
+ RTC_DCHECK_EQ(0, error);
+ } else if (extension.name == RtpExtension::kAudioLevel) {
+ error = rtp->SetSendAudioLevelIndicationStatus(channel_id, true,
+ extension.id);
+ RTC_DCHECK_EQ(0, error);
+ } else {
+ RTC_NOTREACHED() << "Registering unsupported RTP extension.";
+ }
+ }
}
AudioSendStream::~AudioSendStream() {
@@ -65,19 +91,38 @@
LOG(LS_INFO) << "~AudioSendStream: " << config_.ToString();
}
+void AudioSendStream::Start() {
+ RTC_DCHECK(thread_checker_.CalledOnValidThread());
+}
+
+void AudioSendStream::Stop() {
+ RTC_DCHECK(thread_checker_.CalledOnValidThread());
+}
+
+void AudioSendStream::SignalNetworkState(NetworkState state) {
+ RTC_DCHECK(thread_checker_.CalledOnValidThread());
+}
+
+bool AudioSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
+ // TODO(solenberg): Tests call this function on a network thread, libjingle
+ // calls on the worker thread. We should move towards always using a network
+ // thread. Then this check can be enabled.
+ // RTC_DCHECK(!thread_checker_.CalledOnValidThread());
+ return false;
+}
+
webrtc::AudioSendStream::Stats AudioSendStream::GetStats() const {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
webrtc::AudioSendStream::Stats stats;
stats.local_ssrc = config_.rtp.ssrc;
- internal::AudioState* audio_state =
- static_cast<internal::AudioState*>(audio_state_.get());
- VoiceEngine* voice_engine = audio_state->voice_engine();
- ScopedVoEInterface<VoEAudioProcessing> processing(voice_engine);
- ScopedVoEInterface<VoECodec> codec(voice_engine);
- ScopedVoEInterface<VoERTP_RTCP> rtp(voice_engine);
- ScopedVoEInterface<VoEVolumeControl> volume(voice_engine);
+ ScopedVoEInterface<VoEAudioProcessing> processing(voice_engine());
+ ScopedVoEInterface<VoECodec> codec(voice_engine());
+ ScopedVoEInterface<VoERTP_RTCP> rtp(voice_engine());
+ ScopedVoEInterface<VoEVolumeControl> volume(voice_engine());
unsigned int ssrc = 0;
webrtc::CallStatistics call_stats = {0};
+ // TODO(solenberg): Change error code checking to RTC_CHECK_EQ(..., -1), if
+ // possible...
if (rtp->GetLocalSSRC(config_.voe_channel_id, ssrc) == -1 ||
rtp->GetRTCPStatistics(config_.voe_channel_id, call_stats) == -1) {
return stats;
@@ -153,6 +198,8 @@
}
}
+ internal::AudioState* audio_state =
+ static_cast<internal::AudioState*>(audio_state_.get());
stats.typing_noise_detected = audio_state->typing_noise_detected();
return stats;
@@ -163,24 +210,12 @@
return config_;
}
-void AudioSendStream::Start() {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
-}
-
-void AudioSendStream::Stop() {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
-}
-
-void AudioSendStream::SignalNetworkState(NetworkState state) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
-}
-
-bool AudioSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
- // TODO(solenberg): Tests call this function on a network thread, libjingle
- // calls on the worker thread. We should move towards always using a network
- // thread. Then this check can be enabled.
- // RTC_DCHECK(!thread_checker_.CalledOnValidThread());
- return false;
+VoiceEngine* AudioSendStream::voice_engine() const {
+ internal::AudioState* audio_state =
+ static_cast<internal::AudioState*>(audio_state_.get());
+ VoiceEngine* voice_engine = audio_state->voice_engine();
+ RTC_DCHECK(voice_engine);
+ return voice_engine;
}
} // namespace internal
} // namespace webrtc
diff --git a/webrtc/audio/audio_send_stream.h b/webrtc/audio/audio_send_stream.h
index 3d911c1..a4eb89d 100644
--- a/webrtc/audio/audio_send_stream.h
+++ b/webrtc/audio/audio_send_stream.h
@@ -16,6 +16,9 @@
#include "webrtc/base/thread_checker.h"
namespace webrtc {
+
+class VoiceEngine;
+
namespace internal {
class AudioSendStream final : public webrtc::AudioSendStream {
@@ -36,6 +39,8 @@
const webrtc::AudioSendStream::Config& config() const;
private:
+ VoiceEngine* voice_engine() const;
+
rtc::ThreadChecker thread_checker_;
const webrtc::AudioSendStream::Config config_;
rtc::scoped_refptr<webrtc::AudioState> audio_state_;
diff --git a/webrtc/audio/audio_send_stream_unittest.cc b/webrtc/audio/audio_send_stream_unittest.cc
index ada15ac..1801e9d 100644
--- a/webrtc/audio/audio_send_stream_unittest.cc
+++ b/webrtc/audio/audio_send_stream_unittest.cc
@@ -19,8 +19,14 @@
namespace test {
namespace {
+using testing::_;
+using testing::Return;
+
const int kChannelId = 1;
const uint32_t kSsrc = 1234;
+const char* kCName = "foo_name";
+const int kAudioLevelId = 2;
+const int kAbsSendTimeId = 3;
const int kEchoDelayMedian = 254;
const int kEchoDelayStdDev = -3;
const int kEchoReturnLoss = -65;
@@ -33,21 +39,45 @@
struct ConfigHelper {
ConfigHelper() : stream_config_(nullptr) {
+ using testing::StrEq;
+
EXPECT_CALL(voice_engine_,
- RegisterVoiceEngineObserver(testing::_)).WillOnce(testing::Return(0));
+ RegisterVoiceEngineObserver(_)).WillOnce(Return(0));
EXPECT_CALL(voice_engine_,
- DeRegisterVoiceEngineObserver()).WillOnce(testing::Return(0));
+ DeRegisterVoiceEngineObserver()).WillOnce(Return(0));
AudioState::Config config;
config.voice_engine = &voice_engine_;
audio_state_ = AudioState::Create(config);
+
+ EXPECT_CALL(voice_engine_, SetRTCPStatus(kChannelId, true))
+ .WillOnce(Return(0));
+ EXPECT_CALL(voice_engine_, SetLocalSSRC(kChannelId, kSsrc))
+ .WillOnce(Return(0));
+ EXPECT_CALL(voice_engine_, SetRTCP_CNAME(kChannelId, StrEq(kCName)))
+ .WillOnce(Return(0));
+ EXPECT_CALL(voice_engine_,
+ SetSendAbsoluteSenderTimeStatus(kChannelId, true, kAbsSendTimeId))
+ .WillOnce(Return(0));
+ EXPECT_CALL(voice_engine_,
+ SetSendAudioLevelIndicationStatus(kChannelId, true, kAudioLevelId))
+ .WillOnce(Return(0));
stream_config_.voe_channel_id = kChannelId;
stream_config_.rtp.ssrc = kSsrc;
+ stream_config_.rtp.c_name = kCName;
+ stream_config_.rtp.extensions.push_back(
+ RtpExtension(RtpExtension::kAudioLevel, kAudioLevelId));
+ stream_config_.rtp.extensions.push_back(
+ RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeId));
}
AudioSendStream::Config& config() { return stream_config_; }
rtc::scoped_refptr<AudioState> audio_state() { return audio_state_; }
void SetupMockForGetStats() {
+ using testing::DoAll;
+ using testing::SetArgPointee;
+ using testing::SetArgReferee;
+
std::vector<ReportBlock> report_blocks;
webrtc::ReportBlock block = kReportBlock;
report_blocks.push_back(block); // Has wrong SSRC.
@@ -56,11 +86,6 @@
block.fraction_lost = 0;
report_blocks.push_back(block); // Duplicate SSRC, bad fraction_lost.
- using testing::_;
- using testing::DoAll;
- using testing::Return;
- using testing::SetArgPointee;
- using testing::SetArgReferee;
EXPECT_CALL(voice_engine_, GetLocalSSRC(kChannelId, _))
.WillRepeatedly(DoAll(SetArgReferee<1>(0), Return(0)));
EXPECT_CALL(voice_engine_, GetRTCPStatistics(kChannelId, _))
@@ -83,25 +108,26 @@
}
private:
- MockVoiceEngine voice_engine_;
+ testing::StrictMock<MockVoiceEngine> voice_engine_;
rtc::scoped_refptr<AudioState> audio_state_;
AudioSendStream::Config stream_config_;
};
} // namespace
TEST(AudioSendStreamTest, ConfigToString) {
- const int kAbsSendTimeId = 3;
AudioSendStream::Config config(nullptr);
config.rtp.ssrc = kSsrc;
config.rtp.extensions.push_back(
RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeId));
+ config.rtp.c_name = kCName;
config.voe_channel_id = kChannelId;
config.cng_payload_type = 42;
config.red_payload_type = 17;
EXPECT_EQ(
"{rtp: {ssrc: 1234, extensions: [{name: "
- "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time, id: 3}]}, "
- "voe_channel_id: 1, cng_payload_type: 42, red_payload_type: 17}",
+ "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time, id: 3}], "
+ "c_name: foo_name}, voe_channel_id: 1, cng_payload_type: 42, "
+ "red_payload_type: 17}",
config.ToString());
}
diff --git a/webrtc/audio/audio_state_unittest.cc b/webrtc/audio/audio_state_unittest.cc
index 170eff5..11fbdb4 100644
--- a/webrtc/audio/audio_state_unittest.cc
+++ b/webrtc/audio/audio_state_unittest.cc
@@ -30,7 +30,7 @@
MockVoiceEngine& voice_engine() { return voice_engine_; }
private:
- MockVoiceEngine voice_engine_;
+ testing::StrictMock<MockVoiceEngine> voice_engine_;
AudioState::Config config_;
};
} // namespace
diff --git a/webrtc/audio_send_stream.h b/webrtc/audio_send_stream.h
index 89b73e6..c5db82b 100644
--- a/webrtc/audio_send_stream.h
+++ b/webrtc/audio_send_stream.h
@@ -61,6 +61,9 @@
// RTP header extensions used for the received stream.
std::vector<RtpExtension> extensions;
+
+ // RTCP CNAME, see RFC 3550.
+ std::string c_name;
} rtp;
// Transport for outgoing packets. The transport is expected to exist for
diff --git a/webrtc/call/bitrate_estimator_tests.cc b/webrtc/call/bitrate_estimator_tests.cc
index 6bccb43..54a78ea 100644
--- a/webrtc/call/bitrate_estimator_tests.cc
+++ b/webrtc/call/bitrate_estimator_tests.cc
@@ -118,13 +118,6 @@
virtual ~BitrateEstimatorTest() { EXPECT_TRUE(streams_.empty()); }
virtual void SetUp() {
- EXPECT_CALL(mock_voice_engine_,
- RegisterVoiceEngineObserver(testing::_)).WillOnce(testing::Return(0));
- EXPECT_CALL(mock_voice_engine_,
- DeRegisterVoiceEngineObserver()).WillOnce(testing::Return(0));
- EXPECT_CALL(mock_voice_engine_, GetEventLog())
- .WillRepeatedly(testing::Return(nullptr));
-
AudioState::Config audio_state_config;
audio_state_config.voice_engine = &mock_voice_engine_;
Call::Config config;
@@ -265,7 +258,7 @@
test::FakeDecoder fake_decoder_;
};
- test::MockVoiceEngine mock_voice_engine_;
+ testing::NiceMock<test::MockVoiceEngine> mock_voice_engine_;
TraceObserver receiver_trace_;
rtc::scoped_ptr<test::DirectTransport> send_transport_;
rtc::scoped_ptr<test::DirectTransport> receive_transport_;
diff --git a/webrtc/call/call_unittest.cc b/webrtc/call/call_unittest.cc
index b26024d..75c8238 100644
--- a/webrtc/call/call_unittest.cc
+++ b/webrtc/call/call_unittest.cc
@@ -20,12 +20,6 @@
struct CallHelper {
CallHelper() {
- EXPECT_CALL(voice_engine_,
- RegisterVoiceEngineObserver(testing::_)).WillOnce(testing::Return(0));
- EXPECT_CALL(voice_engine_,
- DeRegisterVoiceEngineObserver()).WillOnce(testing::Return(0));
- EXPECT_CALL(voice_engine_,
- GetEventLog()).WillOnce(testing::Return(nullptr));
webrtc::AudioState::Config audio_state_config;
audio_state_config.voice_engine = &voice_engine_;
webrtc::Call::Config config;
@@ -36,7 +30,7 @@
webrtc::Call* operator->() { return call_.get(); }
private:
- webrtc::test::MockVoiceEngine voice_engine_;
+ testing::NiceMock<webrtc::test::MockVoiceEngine> voice_engine_;
rtc::scoped_ptr<webrtc::Call> call_;
};
} // namespace
diff --git a/webrtc/config.h b/webrtc/config.h
index 4b863c8..114303e 100644
--- a/webrtc/config.h
+++ b/webrtc/config.h
@@ -49,10 +49,13 @@
int red_rtx_payload_type;
};
-// RTP header extension to use for the video stream, see RFC 5285.
+// RTP header extension, see RFC 5285.
struct RtpExtension {
RtpExtension(const std::string& name, int id) : name(name), id(id) {}
std::string ToString() const;
+ bool operator==(const RtpExtension& rhs) const {
+ return name == rhs.name && id == rhs.id;
+ }
static bool IsSupportedForAudio(const std::string& name);
static bool IsSupportedForVideo(const std::string& name);
diff --git a/webrtc/test/mock_voice_engine.h b/webrtc/test/mock_voice_engine.h
index 77b4ec8..dead226 100644
--- a/webrtc/test/mock_voice_engine.h
+++ b/webrtc/test/mock_voice_engine.h
@@ -19,7 +19,7 @@
// NOTE: This class inherits from VoiceEngineImpl so that its clients will be
// able to get the various interfaces as usual, via T::GetInterface().
-class MockVoiceEngine final : public VoiceEngineImpl {
+class MockVoiceEngine : public VoiceEngineImpl {
public:
MockVoiceEngine() : VoiceEngineImpl(new Config(), true) {
// Increase ref count so this object isn't automatically deleted whenever