Remove usage of VoEBase::AssociateSendChannel() from WVoMC.

- Functionality now implemented in AudioReceiveStream and Call.
- Added some missing function to MockChannelProxy.

BUG=webrtc:4690

Review-Url: https://codereview.webrtc.org/2461523002
Cr-Commit-Position: refs/heads/master@{#15072}
This commit is contained in:
solenberg 2016-11-14 11:30:07 -08:00 committed by Commit bot
parent 26b675625f
commit 7602aabdc0
14 changed files with 201 additions and 79 deletions

View File

@ -14,6 +14,7 @@
#include <utility>
#include "webrtc/api/call/audio_sink.h"
#include "webrtc/audio/audio_send_stream.h"
#include "webrtc/audio/audio_state.h"
#include "webrtc/audio/conversion.h"
#include "webrtc/base/checks.h"
@ -143,6 +144,7 @@ AudioReceiveStream::~AudioReceiveStream() {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
LOG(LS_INFO) << "~AudioReceiveStream: " << config_.ToString();
Stop();
channel_proxy_->DisassociateSendChannel();
channel_proxy_->DeRegisterExternalTransport();
channel_proxy_->ResetCongestionControlObjects();
channel_proxy_->SetRtcEventLog(nullptr);
@ -230,6 +232,18 @@ const webrtc::AudioReceiveStream::Config& AudioReceiveStream::config() const {
return config_;
}
void AudioReceiveStream::AssociateSendStream(AudioSendStream* send_stream) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
if (send_stream) {
VoiceEngineImpl* voe_impl = static_cast<VoiceEngineImpl*>(voice_engine());
std::unique_ptr<voe::ChannelProxy> send_channel_proxy =
voe_impl->GetChannelProxy(send_stream->config().voe_channel_id);
channel_proxy_->AssociateSendChannel(*send_channel_proxy.get());
} else {
channel_proxy_->DisassociateSendChannel();
}
}
void AudioReceiveStream::SignalNetworkState(NetworkState state) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
}

View File

@ -30,6 +30,7 @@ class ChannelProxy;
} // namespace voe
namespace internal {
class AudioSendStream;
class AudioReceiveStream final : public webrtc::AudioReceiveStream,
public AudioMixer::Source {
@ -47,6 +48,7 @@ class AudioReceiveStream final : public webrtc::AudioReceiveStream,
void SetSink(std::unique_ptr<AudioSinkInterface> sink) override;
void SetGain(float gain) override;
void AssociateSendStream(AudioSendStream* send_stream);
void SignalNetworkState(NetworkState state);
bool DeliverRtcp(const uint8_t* packet, size_t length);
bool DeliverRtp(const uint8_t* packet,

View File

@ -113,6 +113,7 @@ struct ConfigHelper {
EXPECT_CALL(*channel_proxy_, SetRtcEventLog(testing::IsNull()))
.Times(1)
.After(expect_set);
EXPECT_CALL(*channel_proxy_, DisassociateSendChannel()).Times(1);
return channel_proxy_;
}));
EXPECT_CALL(voice_engine_, StopPlayout(kChannelId)).WillOnce(Return(0));

View File

@ -407,6 +407,14 @@ webrtc::AudioSendStream* Call::CreateAudioSendStream(
audio_send_ssrcs_.end());
audio_send_ssrcs_[config.rtp.ssrc] = send_stream;
}
{
ReadLockScoped read_lock(*receive_crit_);
for (const auto& kv : audio_receive_ssrcs_) {
if (kv.second->config().rtp.local_ssrc == config.rtp.ssrc) {
kv.second->AssociateSendStream(send_stream);
}
}
}
send_stream->SignalNetworkState(audio_network_state_);
UpdateAggregateNetworkState();
return send_stream;
@ -421,11 +429,19 @@ void Call::DestroyAudioSendStream(webrtc::AudioSendStream* send_stream) {
webrtc::internal::AudioSendStream* audio_send_stream =
static_cast<webrtc::internal::AudioSendStream*>(send_stream);
uint32_t ssrc = audio_send_stream->config().rtp.ssrc;
{
WriteLockScoped write_lock(*send_crit_);
size_t num_deleted = audio_send_ssrcs_.erase(
audio_send_stream->config().rtp.ssrc);
RTC_DCHECK(num_deleted == 1);
size_t num_deleted = audio_send_ssrcs_.erase(ssrc);
RTC_DCHECK_EQ(1, num_deleted);
}
{
ReadLockScoped read_lock(*receive_crit_);
for (const auto& kv : audio_receive_ssrcs_) {
if (kv.second->config().rtp.local_ssrc == ssrc) {
kv.second->AssociateSendStream(nullptr);
}
}
}
UpdateAggregateNetworkState();
delete audio_send_stream;
@ -445,6 +461,13 @@ webrtc::AudioReceiveStream* Call::CreateAudioReceiveStream(
audio_receive_ssrcs_[config.rtp.remote_ssrc] = receive_stream;
ConfigureSync(config.sync_group);
}
{
ReadLockScoped read_lock(*send_crit_);
auto it = audio_send_ssrcs_.find(config.rtp.local_ssrc);
if (it != audio_send_ssrcs_.end()) {
receive_stream->AssociateSendStream(it->second);
}
}
receive_stream->SignalNetworkState(audio_network_state_);
UpdateAggregateNetworkState();
return receive_stream;

View File

@ -32,6 +32,7 @@ struct CallHelper {
}
webrtc::Call* operator->() { return call_.get(); }
webrtc::test::MockVoiceEngine* voice_engine() { return &voice_engine_; }
private:
testing::NiceMock<webrtc::test::MockVoiceEngine> voice_engine_;
@ -118,6 +119,102 @@ TEST(CallTest, CreateDestroy_AudioReceiveStreams) {
}
}
TEST(CallTest, CreateDestroy_AssociateAudioSendReceiveStreams_RecvFirst) {
rtc::scoped_refptr<webrtc::AudioDecoderFactory> decoder_factory(
new rtc::RefCountedObject<webrtc::MockAudioDecoderFactory>);
CallHelper call(decoder_factory);
constexpr int kRecvChannelId = 101;
// Set up the mock to create a channel proxy which we know of, so that we can
// add our expectations to it.
test::MockVoEChannelProxy* recv_channel_proxy = nullptr;
EXPECT_CALL(*call.voice_engine(), ChannelProxyFactory(testing::_))
.WillRepeatedly(testing::Invoke([&](int channel_id) {
test::MockVoEChannelProxy* channel_proxy =
new testing::NiceMock<test::MockVoEChannelProxy>();
EXPECT_CALL(*channel_proxy, GetAudioDecoderFactory())
.WillRepeatedly(testing::ReturnRef(decoder_factory));
// If being called for the send channel, save a pointer to the channel
// proxy for later.
if (channel_id == kRecvChannelId) {
EXPECT_FALSE(recv_channel_proxy);
recv_channel_proxy = channel_proxy;
}
return channel_proxy;
}));
AudioReceiveStream::Config recv_config;
recv_config.rtp.remote_ssrc = 42;
recv_config.rtp.local_ssrc = 777;
recv_config.voe_channel_id = kRecvChannelId;
recv_config.decoder_factory = decoder_factory;
AudioReceiveStream* recv_stream = call->CreateAudioReceiveStream(recv_config);
EXPECT_NE(recv_stream, nullptr);
EXPECT_CALL(*recv_channel_proxy, AssociateSendChannel(testing::_)).Times(1);
AudioSendStream::Config send_config(nullptr);
send_config.rtp.ssrc = 777;
send_config.voe_channel_id = 123;
AudioSendStream* send_stream = call->CreateAudioSendStream(send_config);
EXPECT_NE(send_stream, nullptr);
EXPECT_CALL(*recv_channel_proxy, DisassociateSendChannel()).Times(1);
call->DestroyAudioSendStream(send_stream);
EXPECT_CALL(*recv_channel_proxy, DisassociateSendChannel()).Times(1);
call->DestroyAudioReceiveStream(recv_stream);
}
TEST(CallTest, CreateDestroy_AssociateAudioSendReceiveStreams_SendFirst) {
rtc::scoped_refptr<webrtc::AudioDecoderFactory> decoder_factory(
new rtc::RefCountedObject<webrtc::MockAudioDecoderFactory>);
CallHelper call(decoder_factory);
constexpr int kRecvChannelId = 101;
// Set up the mock to create a channel proxy which we know of, so that we can
// add our expectations to it.
test::MockVoEChannelProxy* recv_channel_proxy = nullptr;
EXPECT_CALL(*call.voice_engine(), ChannelProxyFactory(testing::_))
.WillRepeatedly(testing::Invoke([&](int channel_id) {
test::MockVoEChannelProxy* channel_proxy =
new testing::NiceMock<test::MockVoEChannelProxy>();
EXPECT_CALL(*channel_proxy, GetAudioDecoderFactory())
.WillRepeatedly(testing::ReturnRef(decoder_factory));
// If being called for the send channel, save a pointer to the channel
// proxy for later.
if (channel_id == kRecvChannelId) {
EXPECT_FALSE(recv_channel_proxy);
recv_channel_proxy = channel_proxy;
// We need to set this expectation here since the channel proxy is
// created as a side effect of CreateAudioReceiveStream().
EXPECT_CALL(*recv_channel_proxy,
AssociateSendChannel(testing::_)).Times(1);
}
return channel_proxy;
}));
AudioSendStream::Config send_config(nullptr);
send_config.rtp.ssrc = 777;
send_config.voe_channel_id = 123;
AudioSendStream* send_stream = call->CreateAudioSendStream(send_config);
EXPECT_NE(send_stream, nullptr);
AudioReceiveStream::Config recv_config;
recv_config.rtp.remote_ssrc = 42;
recv_config.rtp.local_ssrc = 777;
recv_config.voe_channel_id = kRecvChannelId;
recv_config.decoder_factory = decoder_factory;
AudioReceiveStream* recv_stream = call->CreateAudioReceiveStream(recv_config);
EXPECT_NE(recv_stream, nullptr);
EXPECT_CALL(*recv_channel_proxy, DisassociateSendChannel()).Times(1);
call->DestroyAudioReceiveStream(recv_stream);
call->DestroyAudioSendStream(send_stream);
}
TEST(CallTest, CreateDestroy_FlexfecReceiveStream) {
CallHelper call;
FlexfecReceiveStream::Config config;

View File

@ -57,7 +57,6 @@ class FakeWebRtcVoiceEngine
public webrtc::VoEVolumeControl {
public:
struct Channel {
int associate_send_channel = -1;
std::vector<webrtc::CodecInst> recv_codecs;
size_t neteq_capacity = 0;
bool neteq_fast_accelerate = false;
@ -79,10 +78,6 @@ class FakeWebRtcVoiceEngine
fail_create_channel_ = fail_create_channel;
}
int GetAssociateSendChannel(int channel) {
return channels_[channel]->associate_send_channel;
}
WEBRTC_STUB(Release, ());
// webrtc::VoEBase
@ -125,11 +120,6 @@ class FakeWebRtcVoiceEngine
}
WEBRTC_FUNC(DeleteChannel, (int channel)) {
WEBRTC_CHECK_CHANNEL(channel);
for (const auto& ch : channels_) {
if (ch.second->associate_send_channel == channel) {
ch.second->associate_send_channel = -1;
}
}
delete channels_[channel];
channels_.erase(channel);
return 0;
@ -142,12 +132,8 @@ class FakeWebRtcVoiceEngine
WEBRTC_STUB(StopSend, (int channel));
WEBRTC_STUB(GetVersion, (char version[1024]));
WEBRTC_STUB(LastError, ());
WEBRTC_FUNC(AssociateSendChannel, (int channel,
int accociate_send_channel)) {
WEBRTC_CHECK_CHANNEL(channel);
channels_[channel]->associate_send_channel = accociate_send_channel;
return 0;
}
WEBRTC_STUB(AssociateSendChannel, (int channel,
int accociate_send_channel));
// webrtc::VoECodec
WEBRTC_STUB(NumOfCodecs, ());

View File

@ -2085,10 +2085,6 @@ bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
// TODO(solenberg): Allow applications to set the RTCP SSRC of receive
// streams instead, so we can avoid recreating the streams here.
kv.second->RecreateAudioReceiveStream(ssrc);
int recv_channel = kv.second->channel();
engine()->voe()->base()->AssociateSendChannel(recv_channel, channel);
LOG(LS_INFO) << "VoiceEngine channel #" << recv_channel
<< " is associated with channel #" << channel << ".";
}
}
@ -2110,6 +2106,10 @@ bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) {
it->second->SetSend(false);
// TODO(solenberg): If we're removing the receiver_reports_ssrc_ stream, find
// the first active send stream and use that instead, reassociating receive
// streams.
// Clean up and delete the send stream+channel.
int channel = it->second->channel();
LOG(LS_INFO) << "Removing audio send stream " << ssrc
@ -2182,15 +2182,6 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
}
}
const int send_channel = GetSendChannelId(receiver_reports_ssrc_);
if (send_channel != -1) {
// Associate receive channel with first send channel (so the receive channel
// can obtain RTT from the send channel)
engine()->voe()->base()->AssociateSendChannel(channel, send_channel);
LOG(LS_INFO) << "VoiceEngine channel #" << channel
<< " is associated with channel #" << send_channel << ".";
}
recv_streams_.insert(std::make_pair(
ssrc, new WebRtcAudioReceiveStream(channel, ssrc, receiver_reports_ssrc_,
recv_transport_cc_enabled_,

View File

@ -50,6 +50,7 @@ const cricket::AudioCodec kTelephoneEventCodec(106,
const uint32_t kSsrc1 = 0x99;
const uint32_t kSsrc2 = 2;
const uint32_t kSsrc3 = 3;
const uint32_t kSsrc4 = 0x42;
const uint32_t kSsrcs4[] = { 1, 2, 3, 4 };
constexpr int kRtpHistoryMs = 5000;
@ -3239,42 +3240,29 @@ TEST_F(WebRtcVoiceEngineTestFake, DeliverAudioPacket_Call) {
// All receive channels should be associated with the first send channel,
// since they do not send RTCP SR.
TEST_F(WebRtcVoiceEngineTestFake, AssociateFirstSendChannel) {
TEST_F(WebRtcVoiceEngineTestFake, AssociateFirstSendChannel_SendCreatedFirst) {
EXPECT_TRUE(SetupSendStream());
SetSendParameters(send_parameters_);
int default_channel = voe_.GetLastChannel();
EXPECT_TRUE(AddRecvStream(1));
int recv_ch = voe_.GetLastChannel();
EXPECT_NE(recv_ch, default_channel);
EXPECT_EQ(voe_.GetAssociateSendChannel(recv_ch), default_channel);
EXPECT_TRUE(channel_->AddSendStream(cricket::StreamParams::CreateLegacy(2)));
EXPECT_EQ(voe_.GetAssociateSendChannel(recv_ch), default_channel);
EXPECT_TRUE(AddRecvStream(3));
recv_ch = voe_.GetLastChannel();
EXPECT_NE(recv_ch, default_channel);
EXPECT_EQ(voe_.GetAssociateSendChannel(recv_ch), default_channel);
EXPECT_TRUE(AddRecvStream(kSsrc2));
EXPECT_EQ(kSsrc1, GetRecvStreamConfig(kSsrc2).rtp.local_ssrc);
EXPECT_TRUE(channel_->AddSendStream(
cricket::StreamParams::CreateLegacy(kSsrc3)));
EXPECT_EQ(kSsrc1, GetRecvStreamConfig(kSsrc2).rtp.local_ssrc);
EXPECT_TRUE(AddRecvStream(kSsrc4));
EXPECT_EQ(kSsrc1, GetRecvStreamConfig(kSsrc4).rtp.local_ssrc);
}
TEST_F(WebRtcVoiceEngineTestFake, AssociateChannelResetUponDeleteChannnel) {
EXPECT_TRUE(SetupSendStream());
SetSendParameters(send_parameters_);
EXPECT_TRUE(AddRecvStream(1));
int recv_ch = voe_.GetLastChannel();
EXPECT_TRUE(channel_->AddSendStream(cricket::StreamParams::CreateLegacy(2)));
int send_ch = voe_.GetLastChannel();
// Manually associate |recv_ch| to |send_ch|. This test is to verify a
// deleting logic, i.e., deleting |send_ch| will reset the associate send
// channel of |recv_ch|.This is not a common case, since normally, only the
// default channel can be associated. However, the default is not deletable.
// So we force the |recv_ch| to associate with a non-default channel.
EXPECT_EQ(0, voe_.AssociateSendChannel(recv_ch, send_ch));
EXPECT_EQ(voe_.GetAssociateSendChannel(recv_ch), send_ch);
EXPECT_TRUE(channel_->RemoveSendStream(2));
EXPECT_EQ(voe_.GetAssociateSendChannel(recv_ch), -1);
TEST_F(WebRtcVoiceEngineTestFake, AssociateFirstSendChannel_RecvCreatedFirst) {
EXPECT_TRUE(SetupRecvStream());
EXPECT_EQ(0xFA17FA17u, GetRecvStreamConfig(kSsrc1).rtp.local_ssrc);
EXPECT_TRUE(channel_->AddSendStream(
cricket::StreamParams::CreateLegacy(kSsrc2)));
EXPECT_EQ(kSsrc2, GetRecvStreamConfig(kSsrc1).rtp.local_ssrc);
EXPECT_TRUE(AddRecvStream(kSsrc3));
EXPECT_EQ(kSsrc2, GetRecvStreamConfig(kSsrc3).rtp.local_ssrc);
EXPECT_TRUE(channel_->AddSendStream(
cricket::StreamParams::CreateLegacy(kSsrc4)));
EXPECT_EQ(kSsrc2, GetRecvStreamConfig(kSsrc1).rtp.local_ssrc);
EXPECT_EQ(kSsrc2, GetRecvStreamConfig(kSsrc3).rtp.local_ssrc);
}
TEST_F(WebRtcVoiceEngineTestFake, SetRawAudioSink) {

View File

@ -44,9 +44,10 @@ class MockVoEChannelProxy : public voe::ChannelProxy {
MOCK_CONST_METHOD0(GetDelayEstimate, uint32_t());
MOCK_METHOD1(SetSendTelephoneEventPayloadType, bool(int payload_type));
MOCK_METHOD2(SendTelephoneEventOutband, bool(int event, int duration_ms));
MOCK_METHOD1(SetInputMute, void(bool muted));
MOCK_METHOD1(SetBitrate, void(int bitrate_bps));
// TODO(solenberg): Talk the compiler into accepting this mock method:
// MOCK_METHOD1(SetSink, void(std::unique_ptr<AudioSinkInterface> sink));
MOCK_METHOD1(SetInputMute, void(bool muted));
MOCK_METHOD1(RegisterExternalTransport, void(Transport* transport));
MOCK_METHOD0(DeRegisterExternalTransport, void());
MOCK_METHOD3(ReceivedRTPPacket, bool(const uint8_t* packet,
@ -57,13 +58,19 @@ class MockVoEChannelProxy : public voe::ChannelProxy {
const rtc::scoped_refptr<AudioDecoderFactory>&());
MOCK_METHOD1(SetChannelOutputVolumeScaling, void(float scaling));
MOCK_METHOD1(SetRtcEventLog, void(RtcEventLog* event_log));
MOCK_METHOD1(SetTransportOverhead, void(int transport_overhead_per_packet));
MOCK_METHOD1(SetBitrate, void(int bitrate_bps));
MOCK_METHOD1(EnableAudioNetworkAdaptor,
void(const std::string& config_string));
MOCK_METHOD0(DisableAudioNetworkAdaptor, void());
MOCK_METHOD2(SetReceiverFrameLengthRange,
void(int min_frame_length_ms, int max_frame_length_ms));
MOCK_METHOD2(GetAudioFrameWithInfo,
AudioMixer::Source::AudioFrameInfo(int sample_rate_hz,
AudioFrame* audio_frame));
MOCK_CONST_METHOD0(NeededFrequency, int());
MOCK_METHOD1(SetTransportOverhead, void(int transport_overhead_per_packet));
MOCK_METHOD1(AssociateSendChannel,
void(const ChannelProxy& send_channel_proxy));
MOCK_METHOD0(DisassociateSendChannel, void());
};
} // namespace test
} // namespace webrtc

View File

@ -36,7 +36,7 @@ class MockVoiceEngine : public VoiceEngineImpl {
++_ref_count;
// We add this default behavior to make the mock easier to use in tests. It
// will create a NiceMock of a voe::ChannelProxy.
// TODO(ossu): As long as AudioReceiveStream is implmented as a wrapper
// TODO(ossu): As long as AudioReceiveStream is implemented as a wrapper
// around Channel, we need to make sure ChannelProxy returns the same
// decoder factory as the one passed in when creating an AudioReceiveStream.
ON_CALL(*this, ChannelProxyFactory(testing::_))
@ -48,7 +48,7 @@ class MockVoiceEngine : public VoiceEngineImpl {
return proxy;
}));
}
~MockVoiceEngine() /* override */ {
virtual ~MockVoiceEngine() /* override */ {
// Decrease ref count before base class d-tor is called; otherwise it will
// trigger an assertion.
--_ref_count;
@ -57,7 +57,7 @@ class MockVoiceEngine : public VoiceEngineImpl {
MOCK_METHOD1(ChannelProxyFactory, voe::ChannelProxy*(int channel_id));
// VoiceEngineImpl
std::unique_ptr<voe::ChannelProxy> GetChannelProxy(
virtual std::unique_ptr<voe::ChannelProxy> GetChannelProxy(
int channel_id) /* override */ {
return std::unique_ptr<voe::ChannelProxy>(ChannelProxyFactory(channel_id));
}

View File

@ -2813,6 +2813,13 @@ uint32_t Channel::EncodeAndSend() {
return 0;
}
void Channel::set_associate_send_channel(const ChannelOwner& channel) {
RTC_DCHECK(!channel.channel() ||
channel.channel()->ChannelId() != _channelId);
rtc::CritScope lock(&assoc_send_channel_lock_);
associate_send_channel_ = channel;
}
void Channel::DisassociateSendChannel(int channel_id) {
rtc::CritScope lock(&assoc_send_channel_lock_);
Channel* channel = associate_send_channel_.channel();

View File

@ -405,12 +405,7 @@ class Channel
// Associate to a send channel.
// Used for obtaining RTT for a receive-only channel.
void set_associate_send_channel(const ChannelOwner& channel) {
assert(_channelId != channel.channel()->ChannelId());
rtc::CritScope lock(&assoc_send_channel_lock_);
associate_send_channel_ = channel;
}
void set_associate_send_channel(const ChannelOwner& channel);
// Disassociate a send channel if it was associated.
void DisassociateSendChannel(int channel_id);

View File

@ -236,6 +236,17 @@ void ChannelProxy::SetTransportOverhead(int transport_overhead_per_packet) {
channel()->SetTransportOverhead(transport_overhead_per_packet);
}
void ChannelProxy::AssociateSendChannel(
const ChannelProxy& send_channel_proxy) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
channel()->set_associate_send_channel(send_channel_proxy.channel_owner_);
}
void ChannelProxy::DisassociateSendChannel() {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
channel()->set_associate_send_channel(ChannelOwner(nullptr));
}
Channel* ChannelProxy::channel() const {
RTC_DCHECK(channel_owner_.channel());
return channel_owner_.channel();

View File

@ -91,10 +91,10 @@ class ChannelProxy {
virtual AudioMixer::Source::AudioFrameInfo GetAudioFrameWithInfo(
int sample_rate_hz,
AudioFrame* audio_frame);
virtual int NeededFrequency() const;
virtual void SetTransportOverhead(int transport_overhead_per_packet);
virtual void AssociateSendChannel(const ChannelProxy& send_channel_proxy);
virtual void DisassociateSendChannel();
private:
Channel* channel() const;