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}
This commit is contained in:
solenberg
2015-11-16 07:34:50 -08:00
committed by Commit bot
parent 633a3aa26f
commit 3a94154035
14 changed files with 225 additions and 227 deletions

View File

@ -188,9 +188,7 @@ class FakeWebRtcVoiceEngine
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 @@ class FakeWebRtcVoiceEngine
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 @@ class FakeWebRtcVoiceEngine
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 @@ class FakeWebRtcVoiceEngine
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 @@ class FakeWebRtcVoiceEngine
}
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 @@ class FakeWebRtcVoiceEngine
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);

View File

@ -396,6 +396,19 @@ webrtc::AudioState::Config MakeAudioStateConfig(VoEWrapper* voe_wrapper) {
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 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
: 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 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
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 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
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 @@ bool WebRtcVoiceMediaChannel::SetSendParameters(
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 @@ bool WebRtcVoiceMediaChannel::SetRecvRtpHeaderExtensions(
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 @@ bool WebRtcVoiceMediaChannel::SetChannelRecvRtpHeaderExtensions(
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 @@ bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
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::AddSendStream(const StreamParams& sp) {
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

View File

@ -245,8 +245,6 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel,
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 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel,
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 WebRtcVoiceMediaChannel final : public VoiceMediaChannel,
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_;

View File

@ -124,12 +124,10 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
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 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
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 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
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 @@ TEST_F(WebRtcVoiceEngineTestFake, CreateAndDeleteMultipleSendStreams) {
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 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsWithMultipleSendStreams) {
// 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 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsWithMultipleSendStreams) {
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 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendWithMultipleSendStreams) {
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 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendWithMultipleSendStreams) {
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 @@ TEST_F(WebRtcVoiceEngineTestFake, TraceFilterViaTraceOptions) {
// 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 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStats) {
// 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 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrcAfterCreatingReceiveChannel) {
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 @@ TEST_F(WebRtcVoiceEngineTestFake, ConfigureCombinedBweForNewRecvStreams) {
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.

View File

@ -20,6 +20,9 @@ namespace webrtc {
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 @@ const AudioDecodingCallStats kAudioDecodeStats = MakeAudioDecodeStatsForTest();
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 @@ struct ConfigHelper {
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 @@ struct ConfigHelper {
private:
MockRemoteBitrateEstimator remote_bitrate_estimator_;
MockVoiceEngine voice_engine_;
testing::StrictMock<MockVoiceEngine> voice_engine_;
rtc::scoped_refptr<AudioState> audio_state_;
AudioReceiveStream::Config stream_config_;
};

View File

@ -34,6 +34,7 @@ std::string AudioSendStream::Config::Rtp::ToString() const {
}
}
ss << ']';
ss << ", c_name: " << c_name;
ss << '}';
return ss.str();
}
@ -58,6 +59,31 @@ AudioSendStream::AudioSendStream(
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 @@ AudioSendStream::~AudioSendStream() {
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 @@ webrtc::AudioSendStream::Stats AudioSendStream::GetStats() const {
}
}
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 @@ const webrtc::AudioSendStream::Config& AudioSendStream::config() const {
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

View File

@ -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 @@ class AudioSendStream final : public webrtc::AudioSendStream {
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_;

View File

@ -19,8 +19,14 @@ namespace webrtc {
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 @@ const ReportBlock kReportBlock = {456, 780, 123, 567, 890, 132, 143, 13354};
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 @@ struct ConfigHelper {
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 @@ struct ConfigHelper {
}
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());
}

View File

@ -30,7 +30,7 @@ struct ConfigHelper {
MockVoiceEngine& voice_engine() { return voice_engine_; }
private:
MockVoiceEngine voice_engine_;
testing::StrictMock<MockVoiceEngine> voice_engine_;
AudioState::Config config_;
};
} // namespace

View File

@ -61,6 +61,9 @@ class AudioSendStream : public SendStream {
// 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

View File

@ -118,13 +118,6 @@ class BitrateEstimatorTest : public test::CallTest {
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 @@ class BitrateEstimatorTest : public test::CallTest {
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_;

View File

@ -20,12 +20,6 @@ namespace {
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 @@ struct CallHelper {
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

View File

@ -49,10 +49,13 @@ struct FecConfig {
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);

View File

@ -19,7 +19,7 @@ namespace test {
// 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