Move ownership of voe::Channel into Audio[Receive|Send]Stream.

* VoEBase contains only stub methods (until downstream code is
  updated).

* voe::Channel and ChannelProxy classes remain, but are now created
  internally to the streams. As a result,
  internal::Audio[Receive|Send]Stream can have a ChannelProxy injected
  for testing.

* Stream classes share Call::module_process_thread_ for their RtpRtcp
  modules, rather than using a separate thread shared only among audio
  streams.

* voe::Channel instances use Call::worker_queue_ for encoding packets,
  rather than having a separate queue for audio (send) streams.

Bug: webrtc:4690
Change-Id: I8059ef224ad13aa0a6ded2cafc52599c7f64d68d
Reviewed-on: https://webrtc-review.googlesource.com/34640
Commit-Queue: Fredrik Solenberg <solenberg@webrtc.org>
Reviewed-by: Oskar Sundbom <ossu@webrtc.org>
Reviewed-by: Henrik Andreassson <henrika@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21578}
This commit is contained in:
Fredrik Solenberg 2018-01-11 13:52:30 +01:00 committed by Commit Bot
parent aa6b24f23c
commit 8f5787a919
51 changed files with 506 additions and 2005 deletions

View File

@ -25,7 +25,6 @@ rtc_static_library("audio") {
"conversion.h",
"null_audio_poller.cc",
"null_audio_poller.h",
"scoped_voe_interface.h",
"time_interval.cc",
"time_interval.h",
]

View File

@ -25,8 +25,6 @@
#include "rtc_base/logging.h"
#include "rtc_base/timeutils.h"
#include "voice_engine/channel_proxy.h"
#include "voice_engine/include/voe_base.h"
#include "voice_engine/voice_engine_impl.h"
namespace webrtc {
@ -53,7 +51,6 @@ std::string AudioReceiveStream::Config::ToString() const {
ss << "{rtp: " << rtp.ToString();
ss << ", rtcp_send_transport: "
<< (rtcp_send_transport ? "(Transport)" : "null");
ss << ", voe_channel_id: " << voe_channel_id;
if (!sync_group.empty()) {
ss << ", sync_group: " << sync_group;
}
@ -62,32 +59,58 @@ std::string AudioReceiveStream::Config::ToString() const {
}
namespace internal {
namespace {
std::unique_ptr<voe::ChannelProxy> CreateChannelAndProxy(
webrtc::AudioState* audio_state,
ProcessThread* module_process_thread,
const webrtc::AudioReceiveStream::Config& config) {
RTC_DCHECK(audio_state);
internal::AudioState* internal_audio_state =
static_cast<internal::AudioState*>(audio_state);
return std::unique_ptr<voe::ChannelProxy>(new voe::ChannelProxy(
std::unique_ptr<voe::Channel>(new voe::Channel(
module_process_thread,
internal_audio_state->audio_device_module(),
config.jitter_buffer_max_packets,
config.jitter_buffer_fast_accelerate,
config.decoder_factory))));
}
} // namespace
AudioReceiveStream::AudioReceiveStream(
RtpStreamReceiverControllerInterface* receiver_controller,
PacketRouter* packet_router,
ProcessThread* module_process_thread,
const webrtc::AudioReceiveStream::Config& config,
const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
webrtc::RtcEventLog* event_log)
: AudioReceiveStream(receiver_controller,
packet_router,
config,
audio_state,
event_log,
CreateChannelAndProxy(audio_state.get(),
module_process_thread,
config)) {}
AudioReceiveStream::AudioReceiveStream(
RtpStreamReceiverControllerInterface* receiver_controller,
PacketRouter* packet_router,
const webrtc::AudioReceiveStream::Config& config,
const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
webrtc::RtcEventLog* event_log)
: audio_state_(audio_state) {
webrtc::RtcEventLog* event_log,
std::unique_ptr<voe::ChannelProxy> channel_proxy)
: audio_state_(audio_state),
channel_proxy_(std::move(channel_proxy)) {
RTC_LOG(LS_INFO) << "AudioReceiveStream: " << config.ToString();
RTC_DCHECK_NE(config.voe_channel_id, -1);
RTC_DCHECK(audio_state_.get());
RTC_DCHECK(receiver_controller);
RTC_DCHECK(packet_router);
RTC_DCHECK(config.decoder_factory);
RTC_DCHECK(audio_state_);
RTC_DCHECK(channel_proxy_);
module_process_thread_checker_.DetachFromThread();
VoiceEngineImpl* voe_impl = static_cast<VoiceEngineImpl*>(voice_engine());
channel_proxy_ = voe_impl->GetChannelProxy(config.voe_channel_id);
// TODO(ossu): This is where we'd like to set the decoder factory to
// use. However, since it needs to be included when constructing Channel, we
// cannot do that until we're able to move Channel ownership into the
// Audio{Send,Receive}Streams. The best we can do is check that we're not
// trying to use two different factories using the different interfaces.
RTC_CHECK(config.decoder_factory);
RTC_CHECK_EQ(config.decoder_factory,
channel_proxy_->GetAudioDecoderFactory());
channel_proxy_->SetRtcEventLog(event_log);
channel_proxy_->RegisterTransport(config.rtcp_send_transport);
@ -204,9 +227,9 @@ int AudioReceiveStream::GetOutputLevel() const {
return channel_proxy_->GetSpeechOutputLevel();
}
void AudioReceiveStream::SetSink(std::unique_ptr<AudioSinkInterface> sink) {
void AudioReceiveStream::SetSink(AudioSinkInterface* sink) {
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
channel_proxy_->SetSink(std::move(sink));
channel_proxy_->SetSink(sink);
}
void AudioReceiveStream::SetGain(float gain) {
@ -278,13 +301,11 @@ void AudioReceiveStream::SetMinimumPlayoutDelay(int delay_ms) {
void AudioReceiveStream::AssociateSendStream(AudioSendStream* send_stream) {
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
if (send_stream) {
VoiceEngineImpl* voe_impl = static_cast<VoiceEngineImpl*>(voice_engine());
std::unique_ptr<voe::ChannelProxy> send_channel_proxy =
voe_impl->GetChannelProxy(send_stream->GetConfig().voe_channel_id);
channel_proxy_->AssociateSendChannel(*send_channel_proxy.get());
channel_proxy_->AssociateSendChannel(send_stream->GetChannelProxy());
} else {
channel_proxy_->DisassociateSendChannel();
}
associated_send_stream_ = send_stream;
}
void AudioReceiveStream::SignalNetworkState(NetworkState state) {
@ -312,10 +333,10 @@ const webrtc::AudioReceiveStream::Config& AudioReceiveStream::config() const {
return config_;
}
VoiceEngine* AudioReceiveStream::voice_engine() const {
auto* voice_engine = audio_state()->voice_engine();
RTC_DCHECK(voice_engine);
return voice_engine;
const AudioSendStream*
AudioReceiveStream::GetAssociatedSendStreamForTesting() const {
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
return associated_send_stream_;
}
internal::AudioState* AudioReceiveStream::audio_state() const {
@ -345,8 +366,6 @@ void AudioReceiveStream::ConfigureStream(AudioReceiveStream* stream,
const auto& old_config = stream->config_;
// Configuration parameters which cannot be changed.
RTC_DCHECK(first_time ||
old_config.voe_channel_id == new_config.voe_channel_id);
RTC_DCHECK(first_time ||
old_config.rtp.remote_ssrc == new_config.rtp.remote_ssrc);
RTC_DCHECK(first_time ||

View File

@ -24,6 +24,7 @@
namespace webrtc {
class PacketRouter;
class ProcessThread;
class RtcEventLog;
class RtpPacketReceived;
class RtpStreamReceiverControllerInterface;
@ -42,9 +43,17 @@ class AudioReceiveStream final : public webrtc::AudioReceiveStream,
public:
AudioReceiveStream(RtpStreamReceiverControllerInterface* receiver_controller,
PacketRouter* packet_router,
ProcessThread* module_process_thread,
const webrtc::AudioReceiveStream::Config& config,
const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
webrtc::RtcEventLog* event_log);
// For unit tests, which need to supply a mock channel proxy.
AudioReceiveStream(RtpStreamReceiverControllerInterface* receiver_controller,
PacketRouter* packet_router,
const webrtc::AudioReceiveStream::Config& config,
const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
webrtc::RtcEventLog* event_log,
std::unique_ptr<voe::ChannelProxy> channel_proxy);
~AudioReceiveStream() override;
// webrtc::AudioReceiveStream implementation.
@ -53,7 +62,7 @@ class AudioReceiveStream final : public webrtc::AudioReceiveStream,
void Stop() override;
webrtc::AudioReceiveStream::Stats GetStats() const override;
int GetOutputLevel() const override;
void SetSink(std::unique_ptr<AudioSinkInterface> sink) override;
void SetSink(AudioSinkInterface* sink) override;
void SetGain(float gain) override;
std::vector<webrtc::RtpSource> GetSources() const override;
@ -79,6 +88,7 @@ class AudioReceiveStream final : public webrtc::AudioReceiveStream,
void SignalNetworkState(NetworkState state);
bool DeliverRtcp(const uint8_t* packet, size_t length);
const webrtc::AudioReceiveStream::Config& config() const;
const AudioSendStream* GetAssociatedSendStreamForTesting() const;
private:
// RFC 5285: Each distinct extension MUST have a unique ID. The value 0 is
@ -94,7 +104,6 @@ class AudioReceiveStream final : public webrtc::AudioReceiveStream,
const Config& new_config,
bool first_time);
VoiceEngine* voice_engine() const;
AudioState* audio_state() const;
rtc::ThreadChecker worker_thread_checker_;
@ -102,6 +111,7 @@ class AudioReceiveStream final : public webrtc::AudioReceiveStream,
webrtc::AudioReceiveStream::Config config_;
rtc::scoped_refptr<webrtc::AudioState> audio_state_;
std::unique_ptr<voe::ChannelProxy> channel_proxy_;
AudioSendStream* associated_send_stream_ = nullptr;
bool playing_ RTC_ACCESS_ON(worker_thread_checker_) = false;

View File

@ -25,7 +25,6 @@
#include "test/gtest.h"
#include "test/mock_audio_decoder_factory.h"
#include "test/mock_voe_channel_proxy.h"
#include "test/mock_voice_engine.h"
namespace webrtc {
namespace test {
@ -48,8 +47,6 @@ AudioDecodingCallStats MakeAudioDecodeStatsForTest() {
return audio_decode_stats;
}
const int kChannelId1 = 2;
const int kChannelId2 = 29;
const uint32_t kRemoteSsrc = 1234;
const uint32_t kLocalSsrc = 5678;
const size_t kOneByteExtensionHeaderLength = 4;
@ -73,61 +70,47 @@ const AudioDecodingCallStats kAudioDecodeStats = MakeAudioDecodeStatsForTest();
struct ConfigHelper {
ConfigHelper()
: decoder_factory_(new rtc::RefCountedObject<MockAudioDecoderFactory>),
audio_mixer_(new rtc::RefCountedObject<MockAudioMixer>()) {
: ConfigHelper(new rtc::RefCountedObject<MockAudioMixer>()) {}
explicit ConfigHelper(rtc::scoped_refptr<MockAudioMixer> audio_mixer)
: audio_mixer_(audio_mixer) {
using testing::Invoke;
AudioState::Config config;
config.voice_engine = &voice_engine_;
config.audio_mixer = audio_mixer_;
config.audio_processing = new rtc::RefCountedObject<MockAudioProcessing>();
config.audio_device_module =
new rtc::RefCountedObject<MockAudioDeviceModule>();
new rtc::RefCountedObject<testing::NiceMock<MockAudioDeviceModule>>();
audio_state_ = AudioState::Create(config);
EXPECT_CALL(voice_engine_, ChannelProxyFactory(kChannelId1))
.WillOnce(Invoke([this](int channel_id) {
EXPECT_FALSE(channel_proxy_);
channel_proxy_ = new testing::StrictMock<MockVoEChannelProxy>();
EXPECT_CALL(*channel_proxy_, SetLocalSSRC(kLocalSsrc)).Times(1);
EXPECT_CALL(*channel_proxy_, SetNACKStatus(true, 15)).Times(1);
EXPECT_CALL(*channel_proxy_,
SetReceiveAudioLevelIndicationStatus(true, kAudioLevelId))
.Times(1);
EXPECT_CALL(*channel_proxy_,
EnableReceiveTransportSequenceNumber(kTransportSequenceNumberId))
.Times(1);
EXPECT_CALL(*channel_proxy_,
RegisterReceiverCongestionControlObjects(&packet_router_))
.Times(1);
EXPECT_CALL(*channel_proxy_, ResetReceiverCongestionControlObjects())
.Times(1);
EXPECT_CALL(*channel_proxy_, RegisterTransport(nullptr)).Times(2);
EXPECT_CALL(*channel_proxy_, GetAudioDecoderFactory())
.WillOnce(ReturnRef(decoder_factory_));
testing::Expectation expect_set =
EXPECT_CALL(*channel_proxy_, SetRtcEventLog(&event_log_))
.Times(1);
EXPECT_CALL(*channel_proxy_, SetRtcEventLog(testing::IsNull()))
.Times(1)
.After(expect_set);
EXPECT_CALL(*channel_proxy_, DisassociateSendChannel()).Times(1);
EXPECT_CALL(*channel_proxy_, SetReceiveCodecs(_))
.WillRepeatedly(
Invoke([](const std::map<int, SdpAudioFormat>& codecs) {
EXPECT_THAT(codecs, testing::IsEmpty());
}));
return channel_proxy_;
}));
EXPECT_CALL(voice_engine_, ChannelProxyFactory(kChannelId2))
.WillRepeatedly(Invoke([this](int channel_id) {
testing::NiceMock<MockVoEChannelProxy>* proxy =
new testing::NiceMock<MockVoEChannelProxy>();
EXPECT_CALL(*proxy, GetAudioDecoderFactory())
.WillOnce(ReturnRef(decoder_factory_));
return proxy;
}));
stream_config_.voe_channel_id = kChannelId1;
channel_proxy_ = new testing::StrictMock<MockVoEChannelProxy>();
EXPECT_CALL(*channel_proxy_, SetLocalSSRC(kLocalSsrc)).Times(1);
EXPECT_CALL(*channel_proxy_, SetNACKStatus(true, 15)).Times(1);
EXPECT_CALL(*channel_proxy_,
SetReceiveAudioLevelIndicationStatus(true, kAudioLevelId))
.Times(1);
EXPECT_CALL(*channel_proxy_,
EnableReceiveTransportSequenceNumber(kTransportSequenceNumberId))
.Times(1);
EXPECT_CALL(*channel_proxy_,
RegisterReceiverCongestionControlObjects(&packet_router_))
.Times(1);
EXPECT_CALL(*channel_proxy_, ResetReceiverCongestionControlObjects())
.Times(1);
EXPECT_CALL(*channel_proxy_, RegisterTransport(nullptr)).Times(2);
testing::Expectation expect_set =
EXPECT_CALL(*channel_proxy_, SetRtcEventLog(&event_log_))
.Times(1);
EXPECT_CALL(*channel_proxy_, SetRtcEventLog(testing::IsNull()))
.Times(1)
.After(expect_set);
EXPECT_CALL(*channel_proxy_, DisassociateSendChannel()).Times(1);
EXPECT_CALL(*channel_proxy_, SetReceiveCodecs(_))
.WillRepeatedly(
Invoke([](const std::map<int, SdpAudioFormat>& codecs) {
EXPECT_THAT(codecs, testing::IsEmpty());
}));
stream_config_.rtp.local_ssrc = kLocalSsrc;
stream_config_.rtp.remote_ssrc = kRemoteSsrc;
stream_config_.rtp.nack.rtp_history_ms = 300;
@ -135,20 +118,25 @@ struct ConfigHelper {
RtpExtension(RtpExtension::kAudioLevelUri, kAudioLevelId));
stream_config_.rtp.extensions.push_back(RtpExtension(
RtpExtension::kTransportSequenceNumberUri, kTransportSequenceNumberId));
stream_config_.decoder_factory = decoder_factory_;
stream_config_.decoder_factory =
new rtc::RefCountedObject<MockAudioDecoderFactory>;
}
PacketRouter* packet_router() { return &packet_router_; }
MockRtcEventLog* event_log() { return &event_log_; }
AudioReceiveStream::Config& config() { return stream_config_; }
rtc::scoped_refptr<AudioState> audio_state() { return audio_state_; }
rtc::scoped_refptr<MockAudioMixer> audio_mixer() { return audio_mixer_; }
MockVoiceEngine& voice_engine() { return voice_engine_; }
MockVoEChannelProxy* channel_proxy() { return channel_proxy_; }
RtpStreamReceiverControllerInterface* rtp_stream_receiver_controller() {
return &rtp_stream_receiver_controller_;
std::unique_ptr<internal::AudioReceiveStream> CreateAudioReceiveStream() {
return std::unique_ptr<internal::AudioReceiveStream>(
new internal::AudioReceiveStream(
&rtp_stream_receiver_controller_,
&packet_router_,
stream_config_,
audio_state_,
&event_log_,
std::unique_ptr<voe::ChannelProxy>(channel_proxy_)));
}
AudioReceiveStream::Config& config() { return stream_config_; }
rtc::scoped_refptr<MockAudioMixer> audio_mixer() { return audio_mixer_; }
MockVoEChannelProxy* channel_proxy() { return channel_proxy_; }
void SetupMockForGetStats() {
using testing::DoAll;
using testing::SetArgPointee;
@ -174,9 +162,7 @@ struct ConfigHelper {
private:
PacketRouter packet_router_;
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory_;
MockRtcEventLog event_log_;
testing::StrictMock<MockVoiceEngine> voice_engine_;
rtc::scoped_refptr<AudioState> audio_state_;
rtc::scoped_refptr<MockAudioMixer> audio_mixer_;
AudioReceiveStream::Config stream_config_;
@ -240,32 +226,25 @@ TEST(AudioReceiveStreamTest, ConfigToString) {
AudioReceiveStream::Config config;
config.rtp.remote_ssrc = kRemoteSsrc;
config.rtp.local_ssrc = kLocalSsrc;
config.voe_channel_id = kChannelId1;
config.rtp.extensions.push_back(
RtpExtension(RtpExtension::kAudioLevelUri, kAudioLevelId));
EXPECT_EQ(
"{rtp: {remote_ssrc: 1234, local_ssrc: 5678, transport_cc: off, nack: "
"{rtp_history_ms: 0}, extensions: [{uri: "
"urn:ietf:params:rtp-hdrext:ssrc-audio-level, id: 3}]}, "
"rtcp_send_transport: null, voe_channel_id: 2}",
"rtcp_send_transport: null}",
config.ToString());
}
TEST(AudioReceiveStreamTest, ConstructDestruct) {
ConfigHelper helper;
internal::AudioReceiveStream recv_stream(
helper.rtp_stream_receiver_controller(),
helper.packet_router(),
helper.config(), helper.audio_state(), helper.event_log());
auto recv_stream = helper.CreateAudioReceiveStream();
}
TEST(AudioReceiveStreamTest, ReceiveRtpPacket) {
ConfigHelper helper;
helper.config().rtp.transport_cc = true;
internal::AudioReceiveStream recv_stream(
helper.rtp_stream_receiver_controller(),
helper.packet_router(),
helper.config(), helper.audio_state(), helper.event_log());
auto recv_stream = helper.CreateAudioReceiveStream();
const int kTransportSequenceNumberValue = 1234;
std::vector<uint8_t> rtp_packet = CreateRtpHeaderWithOneByteExtension(
kTransportSequenceNumberId, kTransportSequenceNumberValue, 2);
@ -278,32 +257,25 @@ TEST(AudioReceiveStreamTest, ReceiveRtpPacket) {
EXPECT_CALL(*helper.channel_proxy(),
OnRtpPacket(testing::Ref(parsed_packet)));
recv_stream.OnRtpPacket(parsed_packet);
recv_stream->OnRtpPacket(parsed_packet);
}
TEST(AudioReceiveStreamTest, ReceiveRtcpPacket) {
ConfigHelper helper;
helper.config().rtp.transport_cc = true;
internal::AudioReceiveStream recv_stream(
helper.rtp_stream_receiver_controller(),
helper.packet_router(),
helper.config(), helper.audio_state(), helper.event_log());
auto recv_stream = helper.CreateAudioReceiveStream();
std::vector<uint8_t> rtcp_packet = CreateRtcpSenderReport();
EXPECT_CALL(*helper.channel_proxy(),
ReceivedRTCPPacket(&rtcp_packet[0], rtcp_packet.size()))
.WillOnce(Return(true));
EXPECT_TRUE(recv_stream.DeliverRtcp(&rtcp_packet[0], rtcp_packet.size()));
EXPECT_TRUE(recv_stream->DeliverRtcp(&rtcp_packet[0], rtcp_packet.size()));
}
TEST(AudioReceiveStreamTest, GetStats) {
ConfigHelper helper;
internal::AudioReceiveStream recv_stream(
helper.rtp_stream_receiver_controller(),
helper.packet_router(),
helper.config(), helper.audio_state(), helper.event_log());
auto recv_stream = helper.CreateAudioReceiveStream();
helper.SetupMockForGetStats();
AudioReceiveStream::Stats stats = recv_stream.GetStats();
AudioReceiveStream::Stats stats = recv_stream->GetStats();
EXPECT_EQ(kRemoteSsrc, stats.remote_ssrc);
EXPECT_EQ(static_cast<int64_t>(kCallStats.bytesReceived), stats.bytes_rcvd);
EXPECT_EQ(static_cast<uint32_t>(kCallStats.packetsReceived),
@ -354,62 +326,50 @@ TEST(AudioReceiveStreamTest, GetStats) {
TEST(AudioReceiveStreamTest, SetGain) {
ConfigHelper helper;
internal::AudioReceiveStream recv_stream(
helper.rtp_stream_receiver_controller(),
helper.packet_router(),
helper.config(), helper.audio_state(), helper.event_log());
auto recv_stream = helper.CreateAudioReceiveStream();
EXPECT_CALL(*helper.channel_proxy(),
SetChannelOutputVolumeScaling(FloatEq(0.765f)));
recv_stream.SetGain(0.765f);
recv_stream->SetGain(0.765f);
}
TEST(AudioReceiveStreamTest, StreamsShouldBeAddedToMixerOnceOnStart) {
ConfigHelper helper;
internal::AudioReceiveStream recv_stream1(
helper.rtp_stream_receiver_controller(),
helper.packet_router(),
helper.config(), helper.audio_state(), helper.event_log());
AudioReceiveStream::Config config2 = helper.config();
config2.voe_channel_id = kChannelId2;
internal::AudioReceiveStream recv_stream2(
helper.rtp_stream_receiver_controller(),
helper.packet_router(),
config2, helper.audio_state(), helper.event_log());
ConfigHelper helper1;
ConfigHelper helper2(helper1.audio_mixer());
auto recv_stream1 = helper1.CreateAudioReceiveStream();
auto recv_stream2 = helper2.CreateAudioReceiveStream();
EXPECT_CALL(*helper.channel_proxy(), StartPlayout()).Times(1);
EXPECT_CALL(*helper.channel_proxy(), StopPlayout()).Times(1);
EXPECT_CALL(*helper.audio_mixer(), AddSource(&recv_stream1))
EXPECT_CALL(*helper1.channel_proxy(), StartPlayout()).Times(1);
EXPECT_CALL(*helper2.channel_proxy(), StartPlayout()).Times(1);
EXPECT_CALL(*helper1.channel_proxy(), StopPlayout()).Times(1);
EXPECT_CALL(*helper2.channel_proxy(), StopPlayout()).Times(1);
EXPECT_CALL(*helper1.audio_mixer(), AddSource(recv_stream1.get()))
.WillOnce(Return(true));
EXPECT_CALL(*helper.audio_mixer(), AddSource(&recv_stream2))
EXPECT_CALL(*helper1.audio_mixer(), AddSource(recv_stream2.get()))
.WillOnce(Return(true));
EXPECT_CALL(*helper.audio_mixer(), RemoveSource(&recv_stream1)).Times(1);
EXPECT_CALL(*helper.audio_mixer(), RemoveSource(&recv_stream2)).Times(1);
EXPECT_CALL(*helper1.audio_mixer(), RemoveSource(recv_stream1.get()))
.Times(1);
EXPECT_CALL(*helper1.audio_mixer(), RemoveSource(recv_stream2.get()))
.Times(1);
recv_stream1.Start();
recv_stream2.Start();
recv_stream1->Start();
recv_stream2->Start();
// One more should not result in any more mixer sources added.
recv_stream1.Start();
recv_stream1->Start();
// Stop stream before it is being destructed.
recv_stream2.Stop();
recv_stream2->Stop();
}
TEST(AudioReceiveStreamTest, ReconfigureWithSameConfig) {
ConfigHelper helper;
internal::AudioReceiveStream recv_stream(
helper.rtp_stream_receiver_controller(),
helper.packet_router(),
helper.config(), helper.audio_state(), helper.event_log());
recv_stream.Reconfigure(helper.config());
auto recv_stream = helper.CreateAudioReceiveStream();
recv_stream->Reconfigure(helper.config());
}
TEST(AudioReceiveStreamTest, ReconfigureWithUpdatedConfig) {
ConfigHelper helper;
internal::AudioReceiveStream recv_stream(
helper.rtp_stream_receiver_controller(),
helper.packet_router(),
helper.config(), helper.audio_state(), helper.event_log());
auto recv_stream = helper.CreateAudioReceiveStream();
auto new_config = helper.config();
new_config.rtp.local_ssrc = kLocalSsrc + 1;
@ -433,7 +393,7 @@ TEST(AudioReceiveStreamTest, ReconfigureWithUpdatedConfig) {
EnableReceiveTransportSequenceNumber(kTransportSequenceNumberId + 1))
.Times(1);
recv_stream.Reconfigure(new_config);
recv_stream->Reconfigure(new_config);
}
} // namespace test
} // namespace webrtc

View File

@ -29,17 +29,15 @@
#include "rtc_base/timeutils.h"
#include "system_wrappers/include/field_trial.h"
#include "voice_engine/channel_proxy.h"
#include "voice_engine/voice_engine_impl.h"
namespace webrtc {
namespace internal {
namespace {
// TODO(eladalon): Subsequent CL will make these values experiment-dependent.
constexpr size_t kPacketLossTrackerMaxWindowSizeMs = 15000;
constexpr size_t kPacketLossRateMinNumAckedPackets = 50;
constexpr size_t kRecoverablePacketLossRateMinNumAckedPairs = 40;
namespace {
void CallEncoder(const std::unique_ptr<voe::ChannelProxy>& channel_proxy,
rtc::FunctionView<void(AudioEncoder*)> lambda) {
channel_proxy->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder_ptr) {
@ -47,6 +45,20 @@ void CallEncoder(const std::unique_ptr<voe::ChannelProxy>& channel_proxy,
lambda(encoder_ptr->get());
});
}
std::unique_ptr<voe::ChannelProxy> CreateChannelAndProxy(
webrtc::AudioState* audio_state,
rtc::TaskQueue* worker_queue,
ProcessThread* module_process_thread) {
RTC_DCHECK(audio_state);
internal::AudioState* internal_audio_state =
static_cast<internal::AudioState*>(audio_state);
return std::unique_ptr<voe::ChannelProxy>(new voe::ChannelProxy(
std::unique_ptr<voe::Channel>(new voe::Channel(
worker_queue,
module_process_thread,
internal_audio_state->audio_device_module()))));
}
} // namespace
// TODO(saza): Move this declaration further down when we can use
@ -77,14 +89,38 @@ AudioSendStream::AudioSendStream(
const webrtc::AudioSendStream::Config& config,
const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
rtc::TaskQueue* worker_queue,
ProcessThread* module_process_thread,
RtpTransportControllerSendInterface* transport,
BitrateAllocator* bitrate_allocator,
RtcEventLog* event_log,
RtcpRttStats* rtcp_rtt_stats,
const rtc::Optional<RtpState>& suspended_rtp_state)
: AudioSendStream(config,
audio_state,
worker_queue,
transport,
bitrate_allocator,
event_log,
rtcp_rtt_stats,
suspended_rtp_state,
CreateChannelAndProxy(audio_state.get(),
worker_queue,
module_process_thread)) {}
AudioSendStream::AudioSendStream(
const webrtc::AudioSendStream::Config& config,
const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
rtc::TaskQueue* worker_queue,
RtpTransportControllerSendInterface* transport,
BitrateAllocator* bitrate_allocator,
RtcEventLog* event_log,
RtcpRttStats* rtcp_rtt_stats,
const rtc::Optional<RtpState>& suspended_rtp_state,
std::unique_ptr<voe::ChannelProxy> channel_proxy)
: worker_queue_(worker_queue),
config_(Config(nullptr)),
audio_state_(audio_state),
channel_proxy_(std::move(channel_proxy)),
event_log_(event_log),
bitrate_allocator_(bitrate_allocator),
transport_(transport),
@ -94,13 +130,13 @@ AudioSendStream::AudioSendStream(
rtp_rtcp_module_(nullptr),
suspended_rtp_state_(suspended_rtp_state) {
RTC_LOG(LS_INFO) << "AudioSendStream: " << config.ToString();
RTC_DCHECK_NE(config.voe_channel_id, -1);
RTC_DCHECK(audio_state_.get());
RTC_DCHECK(worker_queue_);
RTC_DCHECK(audio_state_);
RTC_DCHECK(channel_proxy_);
RTC_DCHECK(bitrate_allocator_);
RTC_DCHECK(transport);
RTC_DCHECK(transport->send_side_cc());
VoiceEngineImpl* voe_impl = static_cast<VoiceEngineImpl*>(voice_engine());
channel_proxy_ = voe_impl->GetChannelProxy(config.voe_channel_id);
channel_proxy_->SetRtcEventLog(event_log_);
channel_proxy_->SetRtcpRttStats(rtcp_rtt_stats);
channel_proxy_->SetRTCPStatus(true);
@ -423,6 +459,11 @@ const TimeInterval& AudioSendStream::GetActiveLifetime() const {
return active_lifetime_;
}
const voe::ChannelProxy& AudioSendStream::GetChannelProxy() const {
RTC_DCHECK(channel_proxy_.get());
return *channel_proxy_.get();
}
internal::AudioState* AudioSendStream::audio_state() {
internal::AudioState* audio_state =
static_cast<internal::AudioState*>(audio_state_.get());
@ -437,14 +478,6 @@ const internal::AudioState* AudioSendStream::audio_state() const {
return audio_state;
}
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;
}
void AudioSendStream::StoreEncoderProperties(int sample_rate_hz,
size_t num_channels) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());

View File

@ -25,7 +25,6 @@
#include "voice_engine/transport_feedback_packet_loss_tracker.h"
namespace webrtc {
class VoiceEngine;
class RtcEventLog;
class RtcpBandwidthObserver;
class RtcpRttStats;
@ -45,11 +44,22 @@ class AudioSendStream final : public webrtc::AudioSendStream,
AudioSendStream(const webrtc::AudioSendStream::Config& config,
const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
rtc::TaskQueue* worker_queue,
ProcessThread* module_process_thread,
RtpTransportControllerSendInterface* transport,
BitrateAllocator* bitrate_allocator,
RtcEventLog* event_log,
RtcpRttStats* rtcp_rtt_stats,
const rtc::Optional<RtpState>& suspended_rtp_state);
// For unit tests, which need to supply a mock channel proxy.
AudioSendStream(const webrtc::AudioSendStream::Config& config,
const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
rtc::TaskQueue* worker_queue,
RtpTransportControllerSendInterface* transport,
BitrateAllocator* bitrate_allocator,
RtcEventLog* event_log,
RtcpRttStats* rtcp_rtt_stats,
const rtc::Optional<RtpState>& suspended_rtp_state,
std::unique_ptr<voe::ChannelProxy> channel_proxy);
~AudioSendStream() override;
// webrtc::AudioSendStream implementation.
@ -83,13 +93,13 @@ class AudioSendStream final : public webrtc::AudioSendStream,
RtpState GetRtpState() const;
const TimeInterval& GetActiveLifetime() const;
const voe::ChannelProxy& GetChannelProxy() const;
private:
class TimedTransport;
internal::AudioState* audio_state();
const internal::AudioState* audio_state() const;
VoiceEngine* voice_engine() const;
void StoreEncoderProperties(int sample_rate_hz, size_t num_channels);

View File

@ -33,7 +33,6 @@
#include "test/mock_audio_encoder.h"
#include "test/mock_audio_encoder_factory.h"
#include "test/mock_voe_channel_proxy.h"
#include "test/mock_voice_engine.h"
namespace webrtc {
namespace test {
@ -46,7 +45,6 @@ using testing::Invoke;
using testing::Return;
using testing::StrEq;
const int kChannelId = 1;
const uint32_t kSsrc = 1234;
const char* kCName = "foo_name";
const int kAudioLevelId = 2;
@ -141,7 +139,6 @@ struct ConfigHelper {
using testing::Invoke;
AudioState::Config config;
config.voice_engine = &voice_engine_;
config.audio_mixer = AudioMixerImpl::Create();
config.audio_processing = audio_processing_;
config.audio_device_module =
@ -149,19 +146,12 @@ struct ConfigHelper {
audio_state_ = AudioState::Create(config);
SetupDefaultChannelProxy(audio_bwe_enabled);
EXPECT_CALL(voice_engine_, ChannelProxyFactory(kChannelId))
.WillOnce(Invoke([this](int channel_id) {
return channel_proxy_;
}));
SetupMockForSetupSendCodec(expect_set_encoder_call);
// Use ISAC as default codec so as to prevent unnecessary |voice_engine_|
// Use ISAC as default codec so as to prevent unnecessary |channel_proxy_|
// calls from the default ctor behavior.
stream_config_.send_codec_spec =
AudioSendStream::Config::SendCodecSpec(kIsacPayloadType, kIsacFormat);
stream_config_.voe_channel_id = kChannelId;
stream_config_.rtp.ssrc = kSsrc;
stream_config_.rtp.nack.rtp_history_ms = 200;
stream_config_.rtp.c_name = kCName;
@ -175,18 +165,27 @@ struct ConfigHelper {
stream_config_.max_bitrate_bps = 65000;
}
std::unique_ptr<internal::AudioSendStream> CreateAudioSendStream() {
return std::unique_ptr<internal::AudioSendStream>(
new internal::AudioSendStream(
stream_config_,
audio_state_,
&worker_queue_,
&fake_transport_,
&bitrate_allocator_,
&event_log_,
&rtcp_rtt_stats_,
rtc::nullopt,
std::unique_ptr<voe::ChannelProxy>(channel_proxy_)));
}
AudioSendStream::Config& config() { return stream_config_; }
MockAudioEncoderFactory& mock_encoder_factory() {
return *static_cast<MockAudioEncoderFactory*>(
stream_config_.encoder_factory.get());
}
rtc::scoped_refptr<AudioState> audio_state() { return audio_state_; }
MockVoEChannelProxy* channel_proxy() { return channel_proxy_; }
RtpTransportControllerSendInterface* transport() { return &fake_transport_; }
BitrateAllocator* bitrate_allocator() { return &bitrate_allocator_; }
rtc::TaskQueue* worker_queue() { return &worker_queue_; }
RtcEventLog* event_log() { return &event_log_; }
MockVoiceEngine* voice_engine() { return &voice_engine_; }
static void AddBweToConfig(AudioSendStream::Config* config) {
config->rtp.extensions.push_back(
@ -255,8 +254,6 @@ struct ConfigHelper {
}));
}
RtcpRttStats* rtcp_rtt_stats() { return &rtcp_rtt_stats_; }
void SetupMockForSendTelephoneEvent() {
EXPECT_TRUE(channel_proxy_);
EXPECT_CALL(*channel_proxy_,
@ -305,7 +302,6 @@ struct ConfigHelper {
}
private:
testing::StrictMock<MockVoiceEngine> voice_engine_;
rtc::scoped_refptr<AudioState> audio_state_;
AudioSendStream::Config stream_config_;
testing::StrictMock<MockVoEChannelProxy>* channel_proxy_ = nullptr;
@ -332,7 +328,6 @@ TEST(AudioSendStreamTest, ConfigToString) {
AudioSendStream::Config config(nullptr);
config.rtp.ssrc = kSsrc;
config.rtp.c_name = kCName;
config.voe_channel_id = kChannelId;
config.min_bitrate_bps = 12000;
config.max_bitrate_bps = 34000;
config.send_codec_spec =
@ -347,7 +342,7 @@ TEST(AudioSendStreamTest, ConfigToString) {
"{rtp: {ssrc: 1234, extensions: [{uri: "
"urn:ietf:params:rtp-hdrext:ssrc-audio-level, id: 2}], nack: "
"{rtp_history_ms: 0}, c_name: foo_name}, send_transport: null, "
"voe_channel_id: 1, min_bitrate_bps: 12000, max_bitrate_bps: 34000, "
"min_bitrate_bps: 12000, max_bitrate_bps: 34000, "
"send_codec_spec: {nack_enabled: true, transport_cc_enabled: false, "
"cng_payload_type: 42, payload_type: 103, "
"format: {name: isac, clockrate_hz: 16000, num_channels: 1, "
@ -357,58 +352,40 @@ TEST(AudioSendStreamTest, ConfigToString) {
TEST(AudioSendStreamTest, ConstructDestruct) {
ConfigHelper helper(false, true);
internal::AudioSendStream send_stream(
helper.config(), helper.audio_state(), helper.worker_queue(),
helper.transport(), helper.bitrate_allocator(), helper.event_log(),
helper.rtcp_rtt_stats(), rtc::nullopt);
auto send_stream = helper.CreateAudioSendStream();
}
TEST(AudioSendStreamTest, SendTelephoneEvent) {
ConfigHelper helper(false, true);
internal::AudioSendStream send_stream(
helper.config(), helper.audio_state(), helper.worker_queue(),
helper.transport(), helper.bitrate_allocator(), helper.event_log(),
helper.rtcp_rtt_stats(), rtc::nullopt);
auto send_stream = helper.CreateAudioSendStream();
helper.SetupMockForSendTelephoneEvent();
EXPECT_TRUE(send_stream.SendTelephoneEvent(kTelephoneEventPayloadType,
EXPECT_TRUE(send_stream->SendTelephoneEvent(kTelephoneEventPayloadType,
kTelephoneEventPayloadFrequency, kTelephoneEventCode,
kTelephoneEventDuration));
}
TEST(AudioSendStreamTest, SetMuted) {
ConfigHelper helper(false, true);
internal::AudioSendStream send_stream(
helper.config(), helper.audio_state(), helper.worker_queue(),
helper.transport(), helper.bitrate_allocator(), helper.event_log(),
helper.rtcp_rtt_stats(), rtc::nullopt);
auto send_stream = helper.CreateAudioSendStream();
EXPECT_CALL(*helper.channel_proxy(), SetInputMute(true));
send_stream.SetMuted(true);
send_stream->SetMuted(true);
}
TEST(AudioSendStreamTest, AudioBweCorrectObjectsOnChannelProxy) {
ConfigHelper helper(true, true);
internal::AudioSendStream send_stream(
helper.config(), helper.audio_state(), helper.worker_queue(),
helper.transport(), helper.bitrate_allocator(), helper.event_log(),
helper.rtcp_rtt_stats(), rtc::nullopt);
auto send_stream = helper.CreateAudioSendStream();
}
TEST(AudioSendStreamTest, NoAudioBweCorrectObjectsOnChannelProxy) {
ConfigHelper helper(false, true);
internal::AudioSendStream send_stream(
helper.config(), helper.audio_state(), helper.worker_queue(),
helper.transport(), helper.bitrate_allocator(), helper.event_log(),
helper.rtcp_rtt_stats(), rtc::nullopt);
auto send_stream = helper.CreateAudioSendStream();
}
TEST(AudioSendStreamTest, GetStats) {
ConfigHelper helper(false, true);
internal::AudioSendStream send_stream(
helper.config(), helper.audio_state(), helper.worker_queue(),
helper.transport(), helper.bitrate_allocator(), helper.event_log(),
helper.rtcp_rtt_stats(), rtc::nullopt);
auto send_stream = helper.CreateAudioSendStream();
helper.SetupMockForGetStats();
AudioSendStream::Stats stats = send_stream.GetStats(true);
AudioSendStream::Stats stats = send_stream->GetStats(true);
EXPECT_EQ(kSsrc, stats.local_ssrc);
EXPECT_EQ(static_cast<int64_t>(kCallStats.bytesSent), stats.bytes_sent);
EXPECT_EQ(kCallStats.packetsSent, stats.packets_sent);
@ -441,13 +418,12 @@ TEST(AudioSendStreamTest, GetStats) {
TEST(AudioSendStreamTest, SendCodecAppliesAudioNetworkAdaptor) {
ConfigHelper helper(false, true);
auto stream_config = helper.config();
stream_config.send_codec_spec =
helper.config().send_codec_spec =
AudioSendStream::Config::SendCodecSpec(0, kOpusFormat);
const std::string kAnaConfigString = "abcde";
const std::string kAnaReconfigString = "12345";
stream_config.audio_network_adaptor_config = kAnaConfigString;
helper.config().audio_network_adaptor_config = kAnaConfigString;
EXPECT_CALL(helper.mock_encoder_factory(), MakeAudioEncoderMock(_, _, _))
.WillOnce(Invoke([&kAnaConfigString, &kAnaReconfigString](
@ -463,25 +439,22 @@ TEST(AudioSendStreamTest, SendCodecAppliesAudioNetworkAdaptor) {
*return_value = std::move(mock_encoder);
}));
internal::AudioSendStream send_stream(
stream_config, helper.audio_state(), helper.worker_queue(),
helper.transport(), helper.bitrate_allocator(), helper.event_log(),
helper.rtcp_rtt_stats(), rtc::nullopt);
auto send_stream = helper.CreateAudioSendStream();
auto stream_config = helper.config();
stream_config.audio_network_adaptor_config = kAnaReconfigString;
helper.SetupMockForModifyEncoder();
send_stream.Reconfigure(stream_config);
send_stream->Reconfigure(stream_config);
}
// VAD is applied when codec is mono and the CNG frequency matches the codec
// clock rate.
TEST(AudioSendStreamTest, SendCodecCanApplyVad) {
ConfigHelper helper(false, false);
auto stream_config = helper.config();
stream_config.send_codec_spec =
helper.config().send_codec_spec =
AudioSendStream::Config::SendCodecSpec(9, kG722Format);
stream_config.send_codec_spec->cng_payload_type = 105;
helper.config().send_codec_spec->cng_payload_type = 105;
using ::testing::Invoke;
std::unique_ptr<AudioEncoder> stolen_encoder;
EXPECT_CALL(*helper.channel_proxy(), SetEncoderForMock(_, _))
@ -492,10 +465,7 @@ TEST(AudioSendStreamTest, SendCodecCanApplyVad) {
return true;
}));
internal::AudioSendStream send_stream(
stream_config, helper.audio_state(), helper.worker_queue(),
helper.transport(), helper.bitrate_allocator(), helper.event_log(),
helper.rtcp_rtt_stats(), rtc::nullopt);
auto send_stream = helper.CreateAudioSendStream();
// We cannot truly determine if the encoder created is an AudioEncoderCng. It
// is the only reasonable implementation that will return something from
@ -506,24 +476,18 @@ TEST(AudioSendStreamTest, SendCodecCanApplyVad) {
TEST(AudioSendStreamTest, DoesNotPassHigherBitrateThanMaxBitrate) {
ConfigHelper helper(false, true);
internal::AudioSendStream send_stream(
helper.config(), helper.audio_state(), helper.worker_queue(),
helper.transport(), helper.bitrate_allocator(), helper.event_log(),
helper.rtcp_rtt_stats(), rtc::nullopt);
auto send_stream = helper.CreateAudioSendStream();
EXPECT_CALL(*helper.channel_proxy(),
SetBitrate(helper.config().max_bitrate_bps, _));
send_stream.OnBitrateUpdated(helper.config().max_bitrate_bps + 5000, 0.0, 50,
6000);
send_stream->OnBitrateUpdated(helper.config().max_bitrate_bps + 5000, 0.0, 50,
6000);
}
TEST(AudioSendStreamTest, ProbingIntervalOnBitrateUpdated) {
ConfigHelper helper(false, true);
internal::AudioSendStream send_stream(
helper.config(), helper.audio_state(), helper.worker_queue(),
helper.transport(), helper.bitrate_allocator(), helper.event_log(),
helper.rtcp_rtt_stats(), rtc::nullopt);
auto send_stream = helper.CreateAudioSendStream();
EXPECT_CALL(*helper.channel_proxy(), SetBitrate(_, 5000));
send_stream.OnBitrateUpdated(50000, 0.0, 50, 5000);
send_stream->OnBitrateUpdated(50000, 0.0, 50, 5000);
}
// Test that AudioSendStream doesn't recreate the encoder unnecessarily.
@ -537,23 +501,16 @@ TEST(AudioSendStreamTest, DontRecreateEncoder) {
EXPECT_CALL(*helper.channel_proxy(), SetEncoderForMock(_, _))
.WillOnce(Return(true));
auto stream_config = helper.config();
stream_config.send_codec_spec =
helper.config().send_codec_spec =
AudioSendStream::Config::SendCodecSpec(9, kG722Format);
stream_config.send_codec_spec->cng_payload_type = 105;
internal::AudioSendStream send_stream(
stream_config, helper.audio_state(), helper.worker_queue(),
helper.transport(), helper.bitrate_allocator(), helper.event_log(),
helper.rtcp_rtt_stats(), rtc::nullopt);
send_stream.Reconfigure(stream_config);
helper.config().send_codec_spec->cng_payload_type = 105;
auto send_stream = helper.CreateAudioSendStream();
send_stream->Reconfigure(helper.config());
}
TEST(AudioSendStreamTest, ReconfigureTransportCcResetsFirst) {
ConfigHelper helper(false, true);
internal::AudioSendStream send_stream(
helper.config(), helper.audio_state(), helper.worker_queue(),
helper.transport(), helper.bitrate_allocator(), helper.event_log(),
helper.rtcp_rtt_stats(), rtc::nullopt);
auto send_stream = helper.CreateAudioSendStream();
auto new_config = helper.config();
ConfigHelper::AddBweToConfig(&new_config);
EXPECT_CALL(*helper.channel_proxy(),
@ -567,7 +524,7 @@ TEST(AudioSendStreamTest, ReconfigureTransportCcResetsFirst) {
helper.transport(), Ne(nullptr)))
.Times(1);
}
send_stream.Reconfigure(new_config);
send_stream->Reconfigure(new_config);
}
} // namespace test
} // namespace webrtc

View File

@ -27,7 +27,6 @@ namespace internal {
AudioState::AudioState(const AudioState::Config& config)
: config_(config),
voe_base_(config.voice_engine),
audio_transport_(config_.audio_mixer,
config_.audio_processing.get(),
config_.audio_device_module.get()) {
@ -42,11 +41,6 @@ AudioState::~AudioState() {
RTC_DCHECK(sending_streams_.empty());
}
VoiceEngine* AudioState::voice_engine() {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
return config_.voice_engine;
}
bool AudioState::typing_noise_detected() const {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
return audio_transport_.typing_noise_detected();

View File

@ -17,13 +17,11 @@
#include "audio/audio_transport_impl.h"
#include "audio/null_audio_poller.h"
#include "audio/scoped_voe_interface.h"
#include "call/audio_state.h"
#include "rtc_base/constructormagic.h"
#include "rtc_base/criticalsection.h"
#include "rtc_base/refcount.h"
#include "rtc_base/thread_checker.h"
#include "voice_engine/include/voe_base.h"
namespace webrtc {
@ -51,7 +49,11 @@ class AudioState final : public webrtc::AudioState {
Stats GetAudioInputStats() const override;
void SetStereoChannelSwapping(bool enable) override;
VoiceEngine* voice_engine();
AudioDeviceModule* audio_device_module() {
RTC_DCHECK(config_.audio_device_module);
return config_.audio_device_module.get();
}
bool typing_noise_detected() const;
void AddReceivingStream(webrtc::AudioReceiveStream* stream);
@ -74,9 +76,6 @@ class AudioState final : public webrtc::AudioState {
bool recording_enabled_ = true;
bool playout_enabled_ = true;
// We hold one interface pointer to the VoE to make sure it is kept alive.
ScopedVoEInterface<VoEBase> voe_base_;
// Reference count; implementation copied from rtc::RefCountedObject.
// TODO(nisse): Use RefCountedObject or RefCountedBase instead.
mutable volatile int ref_count_ = 0;

View File

@ -16,8 +16,8 @@
#include "modules/audio_device/include/mock_audio_device.h"
#include "modules/audio_mixer/audio_mixer_impl.h"
#include "modules/audio_processing/include/mock_audio_processing.h"
#include "rtc_base/refcountedobject.h"
#include "test/gtest.h"
#include "test/mock_voice_engine.h"
namespace webrtc {
namespace test {
@ -28,7 +28,6 @@ constexpr int kNumberOfChannels = 1;
struct ConfigHelper {
ConfigHelper() : audio_mixer(AudioMixerImpl::Create()) {
audio_state_config.voice_engine = &mock_voice_engine;
audio_state_config.audio_mixer = audio_mixer;
audio_state_config.audio_processing =
new rtc::RefCountedObject<testing::NiceMock<MockAudioProcessing>>();
@ -36,11 +35,9 @@ struct ConfigHelper {
new rtc::RefCountedObject<MockAudioDeviceModule>();
}
AudioState::Config& config() { return audio_state_config; }
MockVoiceEngine& voice_engine() { return mock_voice_engine; }
rtc::scoped_refptr<AudioMixer> mixer() { return audio_mixer; }
private:
testing::StrictMock<MockVoiceEngine> mock_voice_engine;
AudioState::Config audio_state_config;
rtc::scoped_refptr<AudioMixer> audio_mixer;
};
@ -106,13 +103,6 @@ TEST(AudioStateTest, ConstructDestruct) {
new internal::AudioState(helper.config()));
}
TEST(AudioStateTest, GetVoiceEngine) {
ConfigHelper helper;
std::unique_ptr<internal::AudioState> audio_state(
new internal::AudioState(helper.config()));
EXPECT_EQ(audio_state->voice_engine(), &helper.voice_engine());
}
TEST(AudioStateTest, RecordedAudioArrivesAtSingleStream) {
ConfigHelper helper;
std::unique_ptr<internal::AudioState> audio_state(

View File

@ -1,45 +0,0 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef AUDIO_SCOPED_VOE_INTERFACE_H_
#define AUDIO_SCOPED_VOE_INTERFACE_H_
#include "rtc_base/checks.h"
namespace webrtc {
class VoiceEngine;
namespace internal {
// Utility template for obtaining and holding a reference to a VoiceEngine
// interface and making sure it is released when this object goes out of scope.
template<class T> class ScopedVoEInterface {
public:
explicit ScopedVoEInterface(webrtc::VoiceEngine* e)
: ptr_(T::GetInterface(e)) {
RTC_DCHECK(ptr_);
}
~ScopedVoEInterface() {
if (ptr_) {
ptr_->Release();
}
}
T* operator->() {
RTC_DCHECK(ptr_);
return ptr_;
}
private:
T* ptr_;
};
} // namespace internal
} // namespace webrtc
#endif // AUDIO_SCOPED_VOE_INTERFACE_H_

View File

@ -208,6 +208,7 @@ if (rtc_include_tests) {
"../api:libjingle_peerconnection_api",
"../api:mock_audio_mixer",
"../api/audio_codecs:builtin_audio_decoder_factory",
"../audio:audio",
"../logging:rtc_event_log_api",
"../modules/audio_device:mock_audio_device",
"../modules/audio_mixer",

View File

@ -29,11 +29,6 @@
namespace webrtc {
class AudioSinkInterface;
// WORK IN PROGRESS
// This class is under development and is not yet intended for for use outside
// of WebRtc/Libjingle. Please use the VoiceEngine API instead.
// See: https://bugs.chromium.org/p/webrtc/issues/detail?id=4690
class AudioReceiveStream {
public:
struct Stats {
@ -103,12 +98,13 @@ class AudioReceiveStream {
Transport* rtcp_send_transport = nullptr;
// Underlying VoiceEngine handle, used to map AudioReceiveStream to lower-
// level components.
// TODO(solenberg): Remove when VoiceEngine channels are created outside
// of Call.
// TODO(solenberg): Remove once clients don't use it anymore.
int voe_channel_id = -1;
// NetEq settings.
size_t jitter_buffer_max_packets = 50;
bool jitter_buffer_fast_accelerate = false;
// Identifier for an A/V synchronization group. Empty string to disable.
// TODO(pbos): Synchronize streams in a sync group, not just one video
// stream to one audio stream. Tracked by issue webrtc:4762.
@ -135,14 +131,13 @@ class AudioReceiveStream {
virtual int GetOutputLevel() const = 0;
// Sets an audio sink that receives unmixed audio from the receive stream.
// Ownership of the sink is passed to the stream and can be used by the
// caller to do lifetime management (i.e. when the sink's dtor is called).
// Ownership of the sink is managed by the caller.
// Only one sink can be set and passing a null sink clears an existing one.
// NOTE: Audio must still somehow be pulled through AudioTransport for audio
// to stream through this sink. In practice, this happens if mixed audio
// is being pulled+rendered and/or if audio is being pulled for the purposes
// of feeding to the AEC.
virtual void SetSink(std::unique_ptr<AudioSinkInterface> sink) = 0;
virtual void SetSink(AudioSinkInterface* sink) = 0;
// Sets playback gain of the stream, applied when mixing, and thus after it
// is potentially forwarded to any attached AudioSinkInterface implementation.

View File

@ -26,7 +26,6 @@ std::string AudioSendStream::Config::ToString() const {
std::stringstream ss;
ss << "{rtp: " << rtp.ToString();
ss << ", send_transport: " << (send_transport ? "(Transport)" : "null");
ss << ", voe_channel_id: " << voe_channel_id;
ss << ", min_bitrate_bps: " << min_bitrate_bps;
ss << ", max_bitrate_bps: " << max_bitrate_bps;
ss << ", send_codec_spec: "

View File

@ -30,11 +30,6 @@ namespace webrtc {
class AudioFrame;
// WORK IN PROGRESS
// This class is under development and is not yet intended for for use outside
// of WebRtc/Libjingle. Please use the VoiceEngine API instead.
// See: https://bugs.chromium.org/p/webrtc/issues/detail?id=4690
class AudioSendStream {
public:
struct Stats {
@ -92,10 +87,7 @@ class AudioSendStream {
// the entire life of the AudioSendStream and is owned by the API client.
Transport* send_transport = nullptr;
// Underlying VoiceEngine handle, used to map AudioSendStream to lower-level
// components.
// TODO(solenberg): Remove when VoiceEngine channels are created outside
// of Call.
// TODO(solenberg): Remove once clients don't use it anymore.
int voe_channel_id = -1;
// Bitrate limits used for variable audio bitrate streams. Set both to -1 to

View File

@ -21,19 +21,12 @@ class AudioProcessing;
class AudioTransport;
class VoiceEngine;
// WORK IN PROGRESS
// This class is under development and is not yet intended for for use outside
// of WebRtc/Libjingle. Please use the VoiceEngine API instead.
// See: https://bugs.chromium.org/p/webrtc/issues/detail?id=4690
// AudioState holds the state which must be shared between multiple instances of
// webrtc::Call for audio processing purposes.
class AudioState : public rtc::RefCountInterface {
public:
struct Config {
// VoiceEngine used for audio streams and audio/video synchronization.
// AudioState will tickle the VoE refcount to keep it alive for as long as
// the AudioState itself.
// TODO(solenberg): Remove once clients don't use it anymore.
VoiceEngine* voice_engine = nullptr;
// The audio mixer connected to active receive streams. One per

View File

@ -20,7 +20,6 @@
#include "audio/audio_receive_stream.h"
#include "audio/audio_send_stream.h"
#include "audio/audio_state.h"
#include "audio/scoped_voe_interface.h"
#include "audio/time_interval.h"
#include "call/bitrate_allocator.h"
#include "call/call.h"
@ -605,9 +604,9 @@ webrtc::AudioSendStream* Call::CreateAudioSendStream(
}
AudioSendStream* send_stream = new AudioSendStream(
config, config_.audio_state, &worker_queue_, transport_send_.get(),
bitrate_allocator_.get(), event_log_, call_stats_->rtcp_rtt_stats(),
suspended_rtp_state);
config, config_.audio_state, &worker_queue_, module_process_thread_.get(),
transport_send_.get(), bitrate_allocator_.get(), event_log_,
call_stats_->rtcp_rtt_stats(), suspended_rtp_state);
{
WriteLockScoped write_lock(*send_crit_);
RTC_DCHECK(audio_send_ssrcs_.find(config.rtp.ssrc) ==
@ -663,8 +662,8 @@ webrtc::AudioReceiveStream* Call::CreateAudioReceiveStream(
event_log_->Log(rtc::MakeUnique<RtcEventAudioReceiveStreamConfig>(
CreateRtcLogStreamConfig(config)));
AudioReceiveStream* receive_stream = new AudioReceiveStream(
&audio_receiver_controller_, transport_send_->packet_router(), config,
config_.audio_state, event_log_);
&audio_receiver_controller_, transport_send_->packet_router(),
module_process_thread_.get(), config, config_.audio_state, event_log_);
{
WriteLockScoped write_lock(*receive_crit_);
receive_rtp_config_[config.rtp.remote_ssrc] =

View File

@ -40,7 +40,6 @@
#include "test/testsupport/fileutils.h"
#include "test/testsupport/perf_test.h"
#include "video/transport_adapter.h"
#include "voice_engine/include/voe_base.h"
using webrtc::test::DriftingClock;
using webrtc::test::FakeAudioDevice;
@ -152,15 +151,10 @@ void CallPerfTest::TestAudioVideoSync(FecMode fec,
const uint32_t kAudioSendSsrc = 1234;
const uint32_t kAudioRecvSsrc = 5678;
int send_channel_id;
int recv_channel_id;
FakeNetworkPipe::Config audio_net_config;
audio_net_config.queue_delay_ms = 500;
audio_net_config.loss_percent = 5;
VoiceEngine* voice_engine;
VoEBase* voe_base;
VideoRtcpAndSyncObserver observer(Clock::GetRealTimeClock(), test_label);
std::map<uint8_t, MediaType> audio_pt_map;
@ -176,22 +170,13 @@ void CallPerfTest::TestAudioVideoSync(FecMode fec,
task_queue_.SendTask([&]() {
metrics::Reset();
voice_engine = VoiceEngine::Create();
voe_base = VoEBase::GetInterface(voice_engine);
rtc::scoped_refptr<FakeAudioDevice> fake_audio_device =
new rtc::RefCountedObject<FakeAudioDevice>(
FakeAudioDevice::CreatePulsedNoiseCapturer(256, 48000),
FakeAudioDevice::CreateDiscardRenderer(48000), audio_rtp_speed);
EXPECT_EQ(0, fake_audio_device->Init());
EXPECT_EQ(0, voe_base->Init(fake_audio_device.get(), nullptr,
decoder_factory_));
VoEBase::ChannelConfig config;
config.enable_voice_pacing = true;
send_channel_id = voe_base->CreateChannel(config);
recv_channel_id = voe_base->CreateChannel();
AudioState::Config send_audio_state_config;
send_audio_state_config.voice_engine = voice_engine;
send_audio_state_config.audio_mixer = AudioMixerImpl::Create();
send_audio_state_config.audio_processing =
AudioProcessingBuilder().Create();
@ -237,7 +222,6 @@ void CallPerfTest::TestAudioVideoSync(FecMode fec,
CreateMatchingReceiveConfigs(receive_transport.get());
AudioSendStream::Config audio_send_config(audio_send_transport.get());
audio_send_config.voe_channel_id = send_channel_id;
audio_send_config.rtp.ssrc = kAudioSendSsrc;
audio_send_config.send_codec_spec = AudioSendStream::Config::SendCodecSpec(
kAudioSendPayloadType, {"ISAC", 16000, 1});
@ -258,7 +242,6 @@ void CallPerfTest::TestAudioVideoSync(FecMode fec,
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;
audio_recv_config.decoder_factory = decoder_factory_;
audio_recv_config.decoder_map = {
@ -304,13 +287,7 @@ void CallPerfTest::TestAudioVideoSync(FecMode fec,
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();
DestroyCalls();
VoiceEngine::Delete(voice_engine);
});
observer.PrintResults();

View File

@ -15,6 +15,8 @@
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "api/test/mock_audio_mixer.h"
#include "audio/audio_send_stream.h"
#include "audio/audio_receive_stream.h"
#include "call/audio_state.h"
#include "call/call.h"
#include "call/fake_rtp_transport_controller_send.h"
@ -29,16 +31,12 @@
#include "test/gtest.h"
#include "test/mock_audio_decoder_factory.h"
#include "test/mock_transport.h"
#include "test/mock_voice_engine.h"
namespace {
struct CallHelper {
explicit CallHelper(
rtc::scoped_refptr<webrtc::AudioDecoderFactory> decoder_factory = nullptr)
: voice_engine_(decoder_factory) {
CallHelper() {
webrtc::AudioState::Config audio_state_config;
audio_state_config.voice_engine = &voice_engine_;
audio_state_config.audio_mixer =
new rtc::RefCountedObject<webrtc::test::MockAudioMixer>();
audio_state_config.audio_processing =
@ -51,10 +49,8 @@ struct CallHelper {
}
webrtc::Call* operator->() { return call_.get(); }
webrtc::test::MockVoiceEngine* voice_engine() { return &voice_engine_; }
private:
testing::NiceMock<webrtc::test::MockVoiceEngine> voice_engine_;
webrtc::RtcEventLogNullImpl event_log_;
std::unique_ptr<webrtc::Call> call_;
};
@ -70,20 +66,17 @@ TEST(CallTest, CreateDestroy_AudioSendStream) {
CallHelper call;
AudioSendStream::Config config(nullptr);
config.rtp.ssrc = 42;
config.voe_channel_id = 123;
AudioSendStream* stream = call->CreateAudioSendStream(config);
EXPECT_NE(stream, nullptr);
call->DestroyAudioSendStream(stream);
}
TEST(CallTest, CreateDestroy_AudioReceiveStream) {
rtc::scoped_refptr<webrtc::AudioDecoderFactory> decoder_factory(
new rtc::RefCountedObject<webrtc::MockAudioDecoderFactory>);
CallHelper call(decoder_factory);
CallHelper call;
AudioReceiveStream::Config config;
config.rtp.remote_ssrc = 42;
config.voe_channel_id = 123;
config.decoder_factory = decoder_factory;
config.decoder_factory =
new rtc::RefCountedObject<webrtc::MockAudioDecoderFactory>();
AudioReceiveStream* stream = call->CreateAudioReceiveStream(config);
EXPECT_NE(stream, nullptr);
call->DestroyAudioReceiveStream(stream);
@ -92,7 +85,6 @@ TEST(CallTest, CreateDestroy_AudioReceiveStream) {
TEST(CallTest, CreateDestroy_AudioSendStreams) {
CallHelper call;
AudioSendStream::Config config(nullptr);
config.voe_channel_id = 123;
std::list<AudioSendStream*> streams;
for (int i = 0; i < 2; ++i) {
for (uint32_t ssrc = 0; ssrc < 1234567; ssrc += 34567) {
@ -113,12 +105,10 @@ TEST(CallTest, CreateDestroy_AudioSendStreams) {
}
TEST(CallTest, CreateDestroy_AudioReceiveStreams) {
rtc::scoped_refptr<webrtc::AudioDecoderFactory> decoder_factory(
new rtc::RefCountedObject<webrtc::MockAudioDecoderFactory>);
CallHelper call(decoder_factory);
CallHelper call;
AudioReceiveStream::Config config;
config.voe_channel_id = 123;
config.decoder_factory = decoder_factory;
config.decoder_factory =
new rtc::RefCountedObject<webrtc::MockAudioDecoderFactory>();
std::list<AudioReceiveStream*> streams;
for (int i = 0; i < 2; ++i) {
for (uint32_t ssrc = 0; ssrc < 1234567; ssrc += 34567) {
@ -139,112 +129,51 @@ 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);
::testing::NiceMock<MockRtpRtcp> mock_rtp_rtcp;
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));
EXPECT_CALL(*channel_proxy, SetReceiveCodecs(testing::_))
.WillRepeatedly(testing::Invoke(
[](const std::map<int, SdpAudioFormat>& codecs) {
EXPECT_THAT(codecs, testing::IsEmpty());
}));
EXPECT_CALL(*channel_proxy, GetRtpRtcp(testing::_, testing::_))
.WillRepeatedly(testing::SetArgPointee<0>(&mock_rtp_rtcp));
// 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;
}));
CallHelper call;
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;
recv_config.decoder_factory =
new rtc::RefCountedObject<webrtc::MockAudioDecoderFactory>();
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);
internal::AudioReceiveStream* internal_recv_stream =
static_cast<internal::AudioReceiveStream*>(recv_stream);
EXPECT_EQ(send_stream,
internal_recv_stream->GetAssociatedSendStreamForTesting());
call->DestroyAudioSendStream(send_stream);
EXPECT_EQ(nullptr, internal_recv_stream->GetAssociatedSendStreamForTesting());
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);
::testing::NiceMock<MockRtpRtcp> mock_rtp_rtcp;
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));
EXPECT_CALL(*channel_proxy, SetReceiveCodecs(testing::_))
.WillRepeatedly(testing::Invoke(
[](const std::map<int, SdpAudioFormat>& codecs) {
EXPECT_THAT(codecs, testing::IsEmpty());
}));
EXPECT_CALL(*channel_proxy, GetRtpRtcp(testing::_, testing::_))
.WillRepeatedly(testing::SetArgPointee<0>(&mock_rtp_rtcp));
// 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;
}));
CallHelper call;
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;
recv_config.decoder_factory =
new rtc::RefCountedObject<webrtc::MockAudioDecoderFactory>();
AudioReceiveStream* recv_stream = call->CreateAudioReceiveStream(recv_config);
EXPECT_NE(recv_stream, nullptr);
EXPECT_CALL(*recv_channel_proxy, DisassociateSendChannel()).Times(1);
internal::AudioReceiveStream* internal_recv_stream =
static_cast<internal::AudioReceiveStream*>(recv_stream);
EXPECT_EQ(send_stream,
internal_recv_stream->GetAssociatedSendStreamForTesting());
call->DestroyAudioReceiveStream(recv_stream);
call->DestroyAudioSendStream(send_stream);
@ -434,54 +363,15 @@ TEST(CallBitrateTest,
TEST(CallTest, RecreatingAudioStreamWithSameSsrcReusesRtpState) {
constexpr uint32_t kSSRC = 12345;
// There's similar functionality in cricket::VoEWrapper but it's not reachable
// from here. Since we're working on removing VoE interfaces, I doubt it's
// worth making VoEWrapper more easily available.
struct ScopedVoiceEngine {
ScopedVoiceEngine()
: voe(VoiceEngine::Create()),
base(VoEBase::GetInterface(voe)) {}
~ScopedVoiceEngine() {
base->Release();
EXPECT_TRUE(VoiceEngine::Delete(voe));
}
VoiceEngine* voe;
VoEBase* base;
};
ScopedVoiceEngine voice_engine;
AudioState::Config audio_state_config;
audio_state_config.voice_engine = voice_engine.voe;
audio_state_config.audio_mixer =
new rtc::RefCountedObject<test::MockAudioMixer>();
audio_state_config.audio_processing =
new rtc::RefCountedObject<test::MockAudioProcessing>();
audio_state_config.audio_device_module =
new rtc::RefCountedObject<test::MockAudioDeviceModule>();
voice_engine.base->Init(audio_state_config.audio_device_module, nullptr,
CreateBuiltinAudioDecoderFactory());
auto audio_state = AudioState::Create(audio_state_config);
RtcEventLogNullImpl event_log;
Call::Config call_config(&event_log);
call_config.audio_state = audio_state;
std::unique_ptr<Call> call(Call::Create(call_config));
CallHelper call;
auto create_stream_and_get_rtp_state = [&](uint32_t ssrc) {
AudioSendStream::Config config(nullptr);
config.rtp.ssrc = ssrc;
config.voe_channel_id = voice_engine.base->CreateChannel();
AudioSendStream* stream = call->CreateAudioSendStream(config);
VoiceEngineImpl* voe_impl = static_cast<VoiceEngineImpl*>(voice_engine.voe);
auto channel_proxy = voe_impl->GetChannelProxy(config.voe_channel_id);
RtpRtcp* rtp_rtcp = nullptr;
RtpReceiver* rtp_receiver = nullptr; // Unused but required for call.
channel_proxy->GetRtpRtcp(&rtp_rtcp, &rtp_receiver);
const RtpState rtp_state = rtp_rtcp->GetRtpState();
const RtpState rtp_state =
static_cast<internal::AudioSendStream*>(stream)->GetRtpState();
call->DestroyAudioSendStream(stream);
voice_engine.base->DeleteChannel(config.voe_channel_id);
return rtp_state;
};
@ -496,6 +386,7 @@ TEST(CallTest, RecreatingAudioStreamWithSameSsrcReusesRtpState) {
rtp_state2.last_timestamp_time_ms);
EXPECT_EQ(rtp_state1.media_has_been_sent, rtp_state2.media_has_been_sent);
}
TEST(CallBitrateTest, BiggerMaskMinUsed) {
CallBitrateHelper call;
Call::Config::BitrateConfigMask mask;

View File

@ -238,7 +238,6 @@ rtc_static_library("rtc_audio_video") {
"engine/webrtcvideocapturerfactory.h",
"engine/webrtcvideoengine.cc",
"engine/webrtcvideoengine.h",
"engine/webrtcvoe.h",
"engine/webrtcvoiceengine.cc",
"engine/webrtcvoiceengine.h",
@ -427,7 +426,6 @@ if (rtc_include_tests) {
"engine/fakewebrtcvcmfactory.h",
"engine/fakewebrtcvideocapturemodule.h",
"engine/fakewebrtcvideoengine.h",
"engine/fakewebrtcvoiceengine.h",
]
configs += [ ":rtc_unittest_main_config" ]

View File

@ -23,7 +23,6 @@ namespace cricket {
FakeAudioSendStream::FakeAudioSendStream(
int id, const webrtc::AudioSendStream::Config& config)
: id_(id), config_(config) {
RTC_DCHECK(config.voe_channel_id != -1);
}
void FakeAudioSendStream::Reconfigure(
@ -72,7 +71,6 @@ webrtc::AudioSendStream::Stats FakeAudioSendStream::GetStats(
FakeAudioReceiveStream::FakeAudioReceiveStream(
int id, const webrtc::AudioReceiveStream::Config& config)
: id_(id), config_(config) {
RTC_DCHECK(config.voe_channel_id != -1);
}
const webrtc::AudioReceiveStream::Config&
@ -107,9 +105,8 @@ webrtc::AudioReceiveStream::Stats FakeAudioReceiveStream::GetStats() const {
return stats_;
}
void FakeAudioReceiveStream::SetSink(
std::unique_ptr<webrtc::AudioSinkInterface> sink) {
sink_ = std::move(sink);
void FakeAudioReceiveStream::SetSink(webrtc::AudioSinkInterface* sink) {
sink_ = sink;
}
void FakeAudioReceiveStream::SetGain(float gain) {

View File

@ -86,7 +86,7 @@ class FakeAudioReceiveStream final : public webrtc::AudioReceiveStream {
void SetStats(const webrtc::AudioReceiveStream::Stats& stats);
int received_packets() const { return received_packets_; }
bool VerifyLastPacket(const uint8_t* data, size_t length) const;
const webrtc::AudioSinkInterface* sink() const { return sink_.get(); }
const webrtc::AudioSinkInterface* sink() const { return sink_; }
float gain() const { return gain_; }
bool DeliverRtp(const uint8_t* packet,
size_t length,
@ -101,7 +101,7 @@ class FakeAudioReceiveStream final : public webrtc::AudioReceiveStream {
webrtc::AudioReceiveStream::Stats GetStats() const override;
int GetOutputLevel() const override { return 0; }
void SetSink(std::unique_ptr<webrtc::AudioSinkInterface> sink) override;
void SetSink(webrtc::AudioSinkInterface* sink) override;
void SetGain(float gain) override;
std::vector<webrtc::RtpSource> GetSources() const override {
return std::vector<webrtc::RtpSource>();
@ -111,7 +111,7 @@ class FakeAudioReceiveStream final : public webrtc::AudioReceiveStream {
webrtc::AudioReceiveStream::Config config_;
webrtc::AudioReceiveStream::Stats stats_;
int received_packets_ = 0;
std::unique_ptr<webrtc::AudioSinkInterface> sink_;
webrtc::AudioSinkInterface* sink_ = nullptr;
float gain_ = 1.0f;
rtc::Buffer last_packet_;
bool started_ = false;

View File

@ -1,107 +0,0 @@
/*
* Copyright (c) 2010 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MEDIA_ENGINE_FAKEWEBRTCVOICEENGINE_H_
#define MEDIA_ENGINE_FAKEWEBRTCVOICEENGINE_H_
#include <map>
#include <vector>
#include "media/engine/webrtcvoe.h"
#include "rtc_base/checks.h"
namespace cricket {
#define WEBRTC_CHECK_CHANNEL(channel) \
if (channels_.find(channel) == channels_.end()) return -1;
#define WEBRTC_STUB(method, args) \
int method args override { return 0; }
#define WEBRTC_FUNC(method, args) int method args override
class FakeWebRtcVoiceEngine : public webrtc::VoEBase {
public:
struct Channel {
std::vector<webrtc::CodecInst> recv_codecs;
size_t neteq_capacity = 0;
bool neteq_fast_accelerate = false;
};
FakeWebRtcVoiceEngine() {}
~FakeWebRtcVoiceEngine() override {
RTC_CHECK(channels_.empty());
}
bool IsInited() const { return inited_; }
int GetLastChannel() const { return last_channel_; }
int GetNumChannels() const { return static_cast<int>(channels_.size()); }
void set_fail_create_channel(bool fail_create_channel) {
fail_create_channel_ = fail_create_channel;
}
WEBRTC_STUB(Release, ());
// webrtc::VoEBase
WEBRTC_FUNC(Init,
(webrtc::AudioDeviceModule* adm,
webrtc::AudioProcessing* audioproc,
const rtc::scoped_refptr<webrtc::AudioDecoderFactory>&
decoder_factory)) {
inited_ = true;
return 0;
}
void Terminate() override {
inited_ = false;
}
WEBRTC_FUNC(CreateChannel, ()) {
return CreateChannel(webrtc::VoEBase::ChannelConfig());
}
WEBRTC_FUNC(CreateChannel, (const webrtc::VoEBase::ChannelConfig& config)) {
if (fail_create_channel_) {
return -1;
}
Channel* ch = new Channel();
ch->neteq_capacity = config.acm_config.neteq_config.max_packets_in_buffer;
ch->neteq_fast_accelerate =
config.acm_config.neteq_config.enable_fast_accelerate;
channels_[++last_channel_] = ch;
return last_channel_;
}
WEBRTC_FUNC(DeleteChannel, (int channel)) {
WEBRTC_CHECK_CHANNEL(channel);
delete channels_[channel];
channels_.erase(channel);
return 0;
}
size_t GetNetEqCapacity() const {
auto ch = channels_.find(last_channel_);
RTC_DCHECK(ch != channels_.end());
return ch->second->neteq_capacity;
}
bool GetNetEqFastAccelerate() const {
auto ch = channels_.find(last_channel_);
RTC_CHECK(ch != channels_.end());
return ch->second->neteq_fast_accelerate;
}
private:
bool inited_ = false;
int last_channel_ = -1;
std::map<int, Channel*> channels_;
bool fail_create_channel_ = false;
RTC_DISALLOW_COPY_AND_ASSIGN(FakeWebRtcVoiceEngine);
};
} // namespace cricket
#endif // MEDIA_ENGINE_FAKEWEBRTCVOICEENGINE_H_

View File

@ -17,10 +17,10 @@
#include "call/call.h"
#include "media/base/mediaengine.h"
#include "modules/audio_device/include/audio_device.h"
namespace webrtc {
class AudioDecoderFactory;
class AudioDeviceModule;
class AudioMixer;
class AudioProcessing;
class VideoDecoderFactory;

View File

@ -1,89 +0,0 @@
/*
* Copyright (c) 2004 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MEDIA_ENGINE_WEBRTCVOE_H_
#define MEDIA_ENGINE_WEBRTCVOE_H_
#include <memory>
#include "common_types.h" // NOLINT(build/include)
#include "modules/audio_device/include/audio_device.h"
#include "voice_engine/include/voe_base.h"
#include "voice_engine/include/voe_errors.h"
namespace cricket {
// automatically handles lifetime of WebRtc VoiceEngine
class scoped_voe_engine {
public:
explicit scoped_voe_engine(webrtc::VoiceEngine* e) : ptr(e) {}
// RTC_DCHECK, to ensure that there are no leaks at shutdown
~scoped_voe_engine() {
if (ptr) {
const bool success = webrtc::VoiceEngine::Delete(ptr);
RTC_DCHECK(success);
}
}
// Releases the current pointer.
void reset() {
if (ptr) {
const bool success = webrtc::VoiceEngine::Delete(ptr);
RTC_DCHECK(success);
ptr = NULL;
}
}
webrtc::VoiceEngine* get() const { return ptr; }
private:
webrtc::VoiceEngine* ptr;
};
// unique_ptr-like class to handle obtaining and releasing WebRTC interface
// pointers.
template<class T>
class scoped_voe_ptr {
public:
explicit scoped_voe_ptr(const scoped_voe_engine& e)
: ptr(T::GetInterface(e.get())) {}
explicit scoped_voe_ptr(T* p) : ptr(p) {}
~scoped_voe_ptr() { if (ptr) ptr->Release(); }
T* operator->() const { return ptr; }
T* get() const { return ptr; }
// Releases the current pointer.
void reset() {
if (ptr) {
ptr->Release();
ptr = NULL;
}
}
private:
T* ptr;
};
// Utility class for aggregating the various WebRTC interface.
// Fake implementations can also be injected for testing.
class VoEWrapper {
public:
VoEWrapper()
: engine_(webrtc::VoiceEngine::Create()), base_(engine_) {
}
explicit VoEWrapper(webrtc::VoEBase* base)
: engine_(webrtc::VoiceEngine::Create()), base_(base) {}
~VoEWrapper() {}
webrtc::VoiceEngine* engine() const { return engine_.get(); }
webrtc::VoEBase* base() const { return base_.get(); }
private:
scoped_voe_engine engine_;
scoped_voe_ptr<webrtc::VoEBase> base_;
};
} // namespace cricket
#endif // MEDIA_ENGINE_WEBRTCVOE_H_

View File

@ -27,7 +27,6 @@
#include "media/engine/apm_helpers.h"
#include "media/engine/payload_type_mapper.h"
#include "media/engine/webrtcmediaengine.h"
#include "media/engine/webrtcvoe.h"
#include "modules/audio_device/audio_device_impl.h"
#include "modules/audio_mixer/audio_mixer_impl.h"
#include "modules/audio_processing/aec_dump/aec_dump_factory.h"
@ -199,26 +198,11 @@ WebRtcVoiceEngine::WebRtcVoiceEngine(
const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer,
rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing)
: WebRtcVoiceEngine(adm,
encoder_factory,
decoder_factory,
audio_mixer,
audio_processing,
nullptr) {}
WebRtcVoiceEngine::WebRtcVoiceEngine(
webrtc::AudioDeviceModule* adm,
const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory,
const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer,
rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing,
VoEWrapper* voe_wrapper)
: adm_(adm),
encoder_factory_(encoder_factory),
decoder_factory_(decoder_factory),
audio_mixer_(audio_mixer),
apm_(audio_processing),
voe_wrapper_(voe_wrapper) {
apm_(audio_processing) {
// This may be called from any thread, so detach thread checkers.
worker_thread_checker_.DetachFromThread();
signal_thread_checker_.DetachFromThread();
@ -234,7 +218,6 @@ WebRtcVoiceEngine::~WebRtcVoiceEngine() {
RTC_LOG(LS_INFO) << "WebRtcVoiceEngine::~WebRtcVoiceEngine";
if (initialized_) {
StopAecDump();
voe_wrapper_->base()->Terminate();
// Stop AudioDevice.
adm()->StopPlayout();
@ -252,12 +235,6 @@ void WebRtcVoiceEngine::Init() {
low_priority_worker_queue_.reset(
new rtc::TaskQueue("rtc-low-prio", rtc::TaskQueue::Priority::LOW));
// VoEWrapper needs to be created on the worker thread. It's expected to be
// null here unless it's being injected for testing.
if (!voe_wrapper_) {
voe_wrapper_.reset(new VoEWrapper());
}
// Load our audio codec lists.
RTC_LOG(LS_INFO) << "Supported send codecs in order of preference:";
send_codecs_ = CollectCodecs(encoder_factory_->GetSupportedEncoders());
@ -271,8 +248,6 @@ void WebRtcVoiceEngine::Init() {
RTC_LOG(LS_INFO) << ToString(codec);
}
channel_config_.enable_voice_pacing = true;
#if defined(WEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE)
// No ADM supplied? Create a default one.
if (!adm_) {
@ -283,12 +258,10 @@ void WebRtcVoiceEngine::Init() {
RTC_CHECK(adm());
webrtc::adm_helpers::Init(adm());
webrtc::apm_helpers::Init(apm());
RTC_CHECK_EQ(0, voe_wrapper_->base()->Init(adm(), nullptr, decoder_factory_));
// Set up AudioState.
{
webrtc::AudioState::Config config;
config.voice_engine = voe()->engine();
if (audio_mixer_) {
config.audio_mixer = audio_mixer_;
} else {
@ -537,13 +510,13 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
if (options.audio_jitter_buffer_max_packets) {
RTC_LOG(LS_INFO) << "NetEq capacity is "
<< *options.audio_jitter_buffer_max_packets;
channel_config_.acm_config.neteq_config.max_packets_in_buffer =
audio_jitter_buffer_max_packets_ =
std::max(20, *options.audio_jitter_buffer_max_packets);
}
if (options.audio_jitter_buffer_fast_accelerate) {
RTC_LOG(LS_INFO) << "NetEq fast mode? "
<< *options.audio_jitter_buffer_fast_accelerate;
channel_config_.acm_config.neteq_config.enable_fast_accelerate =
audio_jitter_buffer_fast_accelerate_ =
*options.audio_jitter_buffer_fast_accelerate;
}
@ -690,11 +663,6 @@ void WebRtcVoiceEngine::StopAecDump() {
apm()->DetachAecDump();
}
int WebRtcVoiceEngine::CreateVoEChannel() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return voe_wrapper_->base()->CreateChannel(channel_config_);
}
webrtc::AudioDeviceModule* WebRtcVoiceEngine::adm() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
RTC_DCHECK(adm_);
@ -793,7 +761,6 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
: public AudioSource::Sink {
public:
WebRtcAudioSendStream(
int ch,
uint32_t ssrc,
const std::string& c_name,
const std::string track_id,
@ -811,12 +778,10 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
max_send_bitrate_bps_(max_send_bitrate_bps),
rtp_parameters_(CreateRtpParametersWithOneEncoding()) {
RTC_DCHECK_GE(ch, 0);
RTC_DCHECK(call);
RTC_DCHECK(encoder_factory);
config_.rtp.ssrc = ssrc;
config_.rtp.c_name = c_name;
config_.voe_channel_id = ch;
config_.rtp.extensions = extensions;
config_.audio_network_adaptor_config = audio_network_adaptor_config;
config_.encoder_factory = encoder_factory;
@ -970,12 +935,6 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
UpdateSendState();
}
// Accessor to the VoE channel ID.
int channel() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return config_.voe_channel_id;
}
const webrtc::RtpParameters& rtp_parameters() const {
return rtp_parameters_;
}
@ -1153,7 +1112,6 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
public:
WebRtcAudioReceiveStream(
int ch,
uint32_t remote_ssrc,
uint32_t local_ssrc,
bool use_transport_cc,
@ -1163,9 +1121,10 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
webrtc::Call* call,
webrtc::Transport* rtcp_send_transport,
const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
const std::map<int, webrtc::SdpAudioFormat>& decoder_map)
const std::map<int, webrtc::SdpAudioFormat>& decoder_map,
size_t jitter_buffer_max_packets,
bool jitter_buffer_fast_accelerate)
: call_(call), config_() {
RTC_DCHECK_GE(ch, 0);
RTC_DCHECK(call);
config_.rtp.remote_ssrc = remote_ssrc;
config_.rtp.local_ssrc = local_ssrc;
@ -1173,7 +1132,8 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
config_.rtp.nack.rtp_history_ms = use_nack ? kNackRtpHistoryMs : 0;
config_.rtp.extensions = extensions;
config_.rtcp_send_transport = rtcp_send_transport;
config_.voe_channel_id = ch;
config_.jitter_buffer_max_packets = jitter_buffer_max_packets;
config_.jitter_buffer_fast_accelerate = jitter_buffer_fast_accelerate;
config_.sync_group = sync_group;
config_.decoder_factory = decoder_factory;
config_.decoder_map = decoder_map;
@ -1234,14 +1194,10 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
return stream_->GetOutputLevel();
}
int channel() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return config_.voe_channel_id;
}
void SetRawAudioSink(std::unique_ptr<webrtc::AudioSinkInterface> sink) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
stream_->SetSink(std::move(sink));
raw_audio_sink_ = std::move(sink);
stream_->SetSink(raw_audio_sink_.get());
}
void SetOutputVolume(double volume) {
@ -1253,10 +1209,8 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
RTC_DCHECK(stream_);
if (playout) {
RTC_LOG(LS_INFO) << "Starting playout for channel #" << channel();
stream_->Start();
} else {
RTC_LOG(LS_INFO) << "Stopping playout for channel #" << channel();
stream_->Stop();
}
playout_ = playout;
@ -1277,6 +1231,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
stream_ = call_->CreateAudioReceiveStream(config_);
RTC_CHECK(stream_);
SetPlayout(playout_);
stream_->SetSink(raw_audio_sink_.get());
}
void ReconfigureAudioReceiveStream() {
@ -1292,6 +1247,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
// configuration changes.
webrtc::AudioReceiveStream* stream_ = nullptr;
bool playout_ = false;
std::unique_ptr<webrtc::AudioSinkInterface> raw_audio_sink_;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioReceiveStream);
};
@ -1801,24 +1757,6 @@ bool WebRtcVoiceMediaChannel::SetAudioSend(uint32_t ssrc,
return true;
}
int WebRtcVoiceMediaChannel::CreateVoEChannel() {
int id = engine()->CreateVoEChannel();
if (id == -1) {
RTC_LOG(LS_WARNING) << "CreateVoEChannel() failed.";
return -1;
}
return id;
}
bool WebRtcVoiceMediaChannel::DeleteVoEChannel(int channel) {
if (engine()->voe()->base()->DeleteChannel(channel) == -1) {
RTC_LOG(LS_WARNING) << "DeleteChannel(" << channel << ") failed.";
return false;
}
return true;
}
bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::AddSendStream");
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
@ -1827,22 +1765,23 @@ bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
uint32_t ssrc = sp.first_ssrc();
RTC_DCHECK(0 != ssrc);
if (GetSendChannelId(ssrc) != -1) {
if (send_streams_.find(ssrc) != send_streams_.end()) {
RTC_LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
return false;
}
// Create a new channel for sending audio data.
int channel = CreateVoEChannel();
if (channel == -1) {
return false;
}
rtc::Optional<std::string> audio_network_adaptor_config =
GetAudioNetworkAdaptorConfig(options_);
WebRtcAudioSendStream* stream = new WebRtcAudioSendStream(
channel, ssrc, sp.cname, sp.id, send_codec_spec_, send_rtp_extensions_,
max_send_bitrate_bps_, audio_network_adaptor_config, call_, this,
ssrc,
sp.cname,
sp.id,
send_codec_spec_,
send_rtp_extensions_,
max_send_bitrate_bps_,
audio_network_adaptor_config,
call_,
this,
engine()->encoder_factory_);
send_streams_.insert(std::make_pair(ssrc, stream));
@ -1880,15 +1819,8 @@ bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) {
// 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();
RTC_LOG(LS_INFO) << "Removing audio send stream " << ssrc
<< " with VoiceEngine channel #" << channel << ".";
delete it->second;
send_streams_.erase(it);
if (!DeleteVoEChannel(channel)) {
return false;
}
if (send_streams_.empty()) {
SetSend(false);
}
@ -1917,23 +1849,27 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
return true;
}
if (GetReceiveChannelId(ssrc) != -1) {
if (recv_streams_.find(ssrc) != recv_streams_.end()) {
RTC_LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
return false;
}
// Create a new channel for receiving audio data.
const int channel = CreateVoEChannel();
if (channel == -1) {
return false;
}
recv_streams_.insert(std::make_pair(
ssrc,
new WebRtcAudioReceiveStream(
channel, ssrc, receiver_reports_ssrc_, recv_transport_cc_enabled_,
recv_nack_enabled_, sp.sync_label, recv_rtp_extensions_, call_, this,
engine()->decoder_factory_, decoder_map_)));
ssrc,
receiver_reports_ssrc_,
recv_transport_cc_enabled_,
recv_nack_enabled_,
sp.sync_label,
recv_rtp_extensions_,
call_,
this,
engine()->decoder_factory_,
decoder_map_,
engine()->audio_jitter_buffer_max_packets_,
engine()->audio_jitter_buffer_fast_accelerate_)));
recv_streams_[ssrc]->SetPlayout(playout_);
return true;
@ -1953,15 +1889,10 @@ bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) {
MaybeDeregisterUnsignaledRecvStream(ssrc);
const int channel = it->second->channel();
// Clean up and delete the receive stream+channel.
RTC_LOG(LS_INFO) << "Removing audio receive stream " << ssrc
<< " with VoiceEngine channel #" << channel << ".";
it->second->SetRawAudioSink(nullptr);
delete it->second;
recv_streams_.erase(it);
return DeleteVoEChannel(channel);
return true;
}
bool WebRtcVoiceMediaChannel::SetLocalSource(uint32_t ssrc,
@ -2327,24 +2258,6 @@ std::vector<webrtc::RtpSource> WebRtcVoiceMediaChannel::GetSources(
return it->second->GetSources();
}
int WebRtcVoiceMediaChannel::GetReceiveChannelId(uint32_t ssrc) const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
const auto it = recv_streams_.find(ssrc);
if (it != recv_streams_.end()) {
return it->second->channel();
}
return -1;
}
int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
const auto it = send_streams_.find(ssrc);
if (it != send_streams_.end()) {
return it->second->channel();
}
return -1;
}
bool WebRtcVoiceMediaChannel::
MaybeDeregisterUnsignaledRecvStream(uint32_t ssrc) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());

View File

@ -22,7 +22,6 @@
#include "call/call.h"
#include "media/base/rtputils.h"
#include "media/engine/apm_helpers.h"
#include "media/engine/webrtcvoe.h"
#include "modules/audio_processing/include/audio_processing.h"
#include "pc/channel.h"
#include "rtc_base/buffer.h"
@ -37,7 +36,6 @@ namespace cricket {
class AudioDeviceModule;
class AudioMixer;
class AudioSource;
class VoEWrapper;
class WebRtcVoiceMediaChannel;
// WebRtcVoiceEngine is a class to be used with CompositeMediaEngine.
@ -51,14 +49,6 @@ class WebRtcVoiceEngine final {
const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer,
rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing);
// Dependency injection for testing.
WebRtcVoiceEngine(
webrtc::AudioDeviceModule* adm,
const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory,
const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer,
rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing,
VoEWrapper* voe_wrapper);
~WebRtcVoiceEngine();
// Does initialization that needs to occur on the worker thread.
@ -81,8 +71,6 @@ class WebRtcVoiceEngine final {
void RegisterChannel(WebRtcVoiceMediaChannel* channel);
void UnregisterChannel(WebRtcVoiceMediaChannel* channel);
VoEWrapper* voe() { return voe_wrapper_.get(); }
// Starts AEC dump using an existing file. A maximum file size in bytes can be
// specified. When the maximum file size is reached, logging is stopped and
// the file is closed. If max_size_bytes is set to <= 0, no limit will be
@ -125,12 +113,10 @@ class WebRtcVoiceEngine final {
// The audio processing module.
rtc::scoped_refptr<webrtc::AudioProcessing> apm_;
// The primary instance of WebRtc VoiceEngine.
std::unique_ptr<VoEWrapper> voe_wrapper_;
rtc::scoped_refptr<webrtc::AudioState> audio_state_;
std::vector<AudioCodec> send_codecs_;
std::vector<AudioCodec> recv_codecs_;
std::vector<WebRtcVoiceMediaChannel*> channels_;
webrtc::VoEBase::ChannelConfig channel_config_;
bool is_dumping_aec_ = false;
bool initialized_ = false;
@ -145,6 +131,9 @@ class WebRtcVoiceEngine final {
rtc::Optional<bool> experimental_ns_;
rtc::Optional<bool> intelligibility_enhancer_;
rtc::Optional<bool> level_control_;
// Jitter buffer settings for new streams.
size_t audio_jitter_buffer_max_packets_ = 50;
bool audio_jitter_buffer_fast_accelerate_ = false;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcVoiceEngine);
};
@ -224,9 +213,6 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel,
return VoiceMediaChannel::SendRtcp(&packet, rtc::PacketOptions());
}
int GetReceiveChannelId(uint32_t ssrc) const;
int GetSendChannelId(uint32_t ssrc) const;
private:
bool SetOptions(const AudioOptions& options);
bool SetRecvCodecs(const std::vector<AudioCodec>& codecs);

View File

@ -21,7 +21,6 @@
#include "media/base/fakertp.h"
#include "media/base/mediaconstants.h"
#include "media/engine/fakewebrtccall.h"
#include "media/engine/fakewebrtcvoiceengine.h"
#include "media/engine/webrtcvoiceengine.h"
#include "modules/audio_device/include/mock_audio_device.h"
#include "modules/audio_processing/include/mock_audio_processing.h"
@ -133,17 +132,12 @@ TEST(WebRtcVoiceEngineTestStubLibrary, StartupShutdown) {
EXPECT_CALL(*apm, ApplyConfig(_)).WillRepeatedly(SaveArg<0>(&apm_config));
EXPECT_CALL(*apm, SetExtraOptions(testing::_));
EXPECT_CALL(*apm, DetachAecDump());
cricket::FakeWebRtcVoiceEngine voe;
EXPECT_FALSE(voe.IsInited());
{
cricket::WebRtcVoiceEngine engine(
&adm, webrtc::MockAudioEncoderFactory::CreateUnusedFactory(),
webrtc::MockAudioDecoderFactory::CreateUnusedFactory(), nullptr, apm,
new cricket::VoEWrapper(&voe));
webrtc::MockAudioDecoderFactory::CreateUnusedFactory(), nullptr, apm);
engine.Init();
EXPECT_TRUE(voe.IsInited());
}
EXPECT_FALSE(voe.IsInited());
}
class FakeAudioSink : public webrtc::AudioSinkInterface {
@ -167,7 +161,6 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
apm_ns_(*apm_->noise_suppression()),
apm_vd_(*apm_->voice_detection()),
call_(webrtc::Call::Config(&event_log_)),
voe_(),
override_field_trials_(field_trials) {
// AudioDeviceModule.
AdmSetupExpectations(&adm_);
@ -198,8 +191,7 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
auto encoder_factory = webrtc::CreateBuiltinAudioEncoderFactory();
auto decoder_factory = webrtc::CreateBuiltinAudioDecoderFactory();
engine_.reset(new cricket::WebRtcVoiceEngine(
&adm_, encoder_factory, decoder_factory, nullptr, apm_,
new cricket::VoEWrapper(&voe_)));
&adm_, encoder_factory, decoder_factory, nullptr, apm_));
engine_->Init();
send_parameters_.codecs.push_back(kPcmuCodec);
recv_parameters_.codecs.push_back(kPcmuCodec);
@ -708,7 +700,6 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
webrtc::test::MockVoiceDetection& apm_vd_;
webrtc::RtcEventLogNullImpl event_log_;
cricket::FakeCall call_;
cricket::FakeWebRtcVoiceEngine voe_;
std::unique_ptr<cricket::WebRtcVoiceEngine> engine_;
cricket::VoiceMediaChannel* channel_ = nullptr;
cricket::AudioSendParameters send_parameters_;
@ -2644,26 +2635,10 @@ TEST_F(WebRtcVoiceEngineTestFake, AddRecvStreamAfterUnsignaled_Recreate) {
EXPECT_NE(audio_receive_stream_id, streams.front()->id());
}
// Test that we properly handle failures to add a receive stream.
TEST_F(WebRtcVoiceEngineTestFake, AddRecvStreamFail) {
EXPECT_TRUE(SetupChannel());
voe_.set_fail_create_channel(true);
EXPECT_FALSE(AddRecvStream(2));
}
// Test that we properly handle failures to add a send stream.
TEST_F(WebRtcVoiceEngineTestFake, AddSendStreamFail) {
EXPECT_TRUE(SetupChannel());
voe_.set_fail_create_channel(true);
EXPECT_FALSE(channel_->AddSendStream(cricket::StreamParams::CreateLegacy(2)));
}
// Test that AddRecvStream creates new stream.
TEST_F(WebRtcVoiceEngineTestFake, AddRecvStream) {
EXPECT_TRUE(SetupRecvStream());
int channel_num = voe_.GetLastChannel();
EXPECT_TRUE(AddRecvStream(1));
EXPECT_NE(channel_num, voe_.GetLastChannel());
}
// Test that after adding a recv stream, we do not decode more codecs than
@ -2687,10 +2662,13 @@ TEST_F(WebRtcVoiceEngineTestFake, StreamCleanup) {
SetSendParameters(send_parameters_);
EXPECT_TRUE(AddRecvStream(1));
EXPECT_TRUE(AddRecvStream(2));
EXPECT_EQ(3, voe_.GetNumChannels()); // default channel + 2 added
EXPECT_EQ(1, call_.GetAudioSendStreams().size());
EXPECT_EQ(2, call_.GetAudioReceiveStreams().size());
delete channel_;
channel_ = NULL;
EXPECT_EQ(0, voe_.GetNumChannels());
EXPECT_EQ(0, call_.GetAudioSendStreams().size());
EXPECT_EQ(0, call_.GetAudioReceiveStreams().size());
}
TEST_F(WebRtcVoiceEngineTestFake, TestAddRecvStreamFailWithZeroSsrc) {
@ -2698,18 +2676,10 @@ TEST_F(WebRtcVoiceEngineTestFake, TestAddRecvStreamFailWithZeroSsrc) {
EXPECT_FALSE(AddRecvStream(0));
}
TEST_F(WebRtcVoiceEngineTestFake, TestNoLeakingWhenAddRecvStreamFail) {
TEST_F(WebRtcVoiceEngineTestFake, TestAddRecvStreamFailWithSameSsrc) {
EXPECT_TRUE(SetupChannel());
EXPECT_TRUE(AddRecvStream(1));
// Manually delete channel to simulate a failure.
int channel = voe_.GetLastChannel();
EXPECT_EQ(0, voe_.DeleteChannel(channel));
// Add recv stream 2 should work.
EXPECT_TRUE(AddRecvStream(2));
int new_channel = voe_.GetLastChannel();
EXPECT_NE(channel, new_channel);
// The last created channel is deleted too.
EXPECT_EQ(0, voe_.DeleteChannel(new_channel));
EXPECT_FALSE(AddRecvStream(1));
}
// Test the InsertDtmf on default send stream as caller.
@ -2734,6 +2704,7 @@ TEST_F(WebRtcVoiceEngineTestFake, InsertDtmfOnSendStreamAsCallee) {
TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
EXPECT_TRUE(SetupSendStream());
EXPECT_TRUE(AddRecvStream(kSsrcY));
EXPECT_CALL(adm_,
BuiltInAECIsAvailable()).Times(9).WillRepeatedly(Return(false));
EXPECT_CALL(adm_,
@ -2741,15 +2712,15 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
EXPECT_CALL(adm_,
BuiltInNSIsAvailable()).Times(2).WillRepeatedly(Return(false));
EXPECT_EQ(50, voe_.GetNetEqCapacity());
EXPECT_FALSE(voe_.GetNetEqFastAccelerate());
EXPECT_EQ(50, GetRecvStreamConfig(kSsrcY).jitter_buffer_max_packets);
EXPECT_FALSE(GetRecvStreamConfig(kSsrcY).jitter_buffer_fast_accelerate);
// Nothing set in AudioOptions, so everything should be as default.
send_parameters_.options = cricket::AudioOptions();
SetSendParameters(send_parameters_);
EXPECT_TRUE(IsHighPassFilterEnabled());
EXPECT_EQ(50, voe_.GetNetEqCapacity());
EXPECT_FALSE(voe_.GetNetEqFastAccelerate());
EXPECT_EQ(50, GetRecvStreamConfig(kSsrcY).jitter_buffer_max_packets);
EXPECT_FALSE(GetRecvStreamConfig(kSsrcY).jitter_buffer_fast_accelerate);
// Turn echo cancellation off
EXPECT_CALL(apm_ec_, Enable(false)).WillOnce(Return(0));
@ -2992,36 +2963,6 @@ TEST_F(WebRtcVoiceEngineTestFake, TestSetDscpOptions) {
channel->SetInterface(nullptr);
}
TEST_F(WebRtcVoiceEngineTestFake, TestGetReceiveChannelId) {
EXPECT_TRUE(SetupChannel());
cricket::WebRtcVoiceMediaChannel* media_channel =
static_cast<cricket::WebRtcVoiceMediaChannel*>(channel_);
EXPECT_EQ(-1, media_channel->GetReceiveChannelId(0));
EXPECT_TRUE(AddRecvStream(kSsrcX));
int channel_id = voe_.GetLastChannel();
EXPECT_EQ(channel_id, media_channel->GetReceiveChannelId(kSsrcX));
EXPECT_EQ(-1, media_channel->GetReceiveChannelId(kSsrcY));
EXPECT_TRUE(AddRecvStream(kSsrcY));
int channel_id2 = voe_.GetLastChannel();
EXPECT_EQ(channel_id2, media_channel->GetReceiveChannelId(kSsrcY));
}
TEST_F(WebRtcVoiceEngineTestFake, TestGetSendChannelId) {
EXPECT_TRUE(SetupChannel());
cricket::WebRtcVoiceMediaChannel* media_channel =
static_cast<cricket::WebRtcVoiceMediaChannel*>(channel_);
EXPECT_EQ(-1, media_channel->GetSendChannelId(0));
EXPECT_TRUE(channel_->AddSendStream(
cricket::StreamParams::CreateLegacy(kSsrcX)));
int channel_id = voe_.GetLastChannel();
EXPECT_EQ(channel_id, media_channel->GetSendChannelId(kSsrcX));
EXPECT_EQ(-1, media_channel->GetSendChannelId(kSsrcY));
EXPECT_TRUE(channel_->AddSendStream(
cricket::StreamParams::CreateLegacy(kSsrcY)));
int channel_id2 = voe_.GetLastChannel();
EXPECT_EQ(channel_id2, media_channel->GetSendChannelId(kSsrcY));
}
TEST_F(WebRtcVoiceEngineTestFake, SetOutputVolume) {
EXPECT_TRUE(SetupChannel());
EXPECT_FALSE(channel_->SetOutputVolume(kSsrcY, 0.5));
@ -3353,9 +3294,9 @@ TEST(WebRtcVoiceEngineTest, StartupShutdown) {
// Tests that reference counting on the external ADM is correct.
TEST(WebRtcVoiceEngineTest, StartupShutdownWithExternalADM) {
testing::NiceMock<webrtc::test::MockAudioDeviceModule> adm;
EXPECT_CALL(adm, AddRef()).Times(5);
EXPECT_CALL(adm, AddRef()).Times(3);
EXPECT_CALL(adm, Release())
.Times(5)
.Times(3)
.WillRepeatedly(Return(rtc::RefCountReleaseStatus::kDroppedLastRef));
{
rtc::scoped_refptr<webrtc::AudioProcessing> apm =

View File

@ -568,7 +568,6 @@ rtc_source_set("test_common") {
"layer_filtering_transport.h",
"mock_transport.h",
"mock_voe_channel_proxy.h",
"mock_voice_engine.h",
"null_transport.cc",
"null_transport.h",
"rtp_rtcp_observer.h",

View File

@ -21,7 +21,6 @@
#include "rtc_base/event.h"
#include "rtc_base/ptr_util.h"
#include "test/testsupport/fileutils.h"
#include "voice_engine/include/voe_base.h"
namespace webrtc {
namespace test {
@ -67,9 +66,9 @@ void CallTest::RunBaseTest(BaseTest* test) {
fake_recv_audio_device_.get());
apm_send_ = AudioProcessingBuilder().Create();
apm_recv_ = AudioProcessingBuilder().Create();
CreateVoiceEngines();
EXPECT_EQ(0, fake_send_audio_device_->Init());
EXPECT_EQ(0, fake_recv_audio_device_->Init());
AudioState::Config audio_state_config;
audio_state_config.voice_engine = voe_send_.voice_engine;
audio_state_config.audio_mixer = AudioMixerImpl::Create();
audio_state_config.audio_processing = apm_send_;
audio_state_config.audio_device_module = fake_send_audio_device_;
@ -86,7 +85,6 @@ void CallTest::RunBaseTest(BaseTest* test) {
Call::Config recv_config(test->GetReceiverCallConfig());
if (num_audio_streams_ > 0) {
AudioState::Config audio_state_config;
audio_state_config.voice_engine = voe_recv_.voice_engine;
audio_state_config.audio_mixer = AudioMixerImpl::Create();
audio_state_config.audio_processing = apm_recv_;
audio_state_config.audio_device_module = fake_recv_audio_device_;
@ -163,8 +161,6 @@ void CallTest::RunBaseTest(BaseTest* test) {
send_transport_.reset();
receive_transport_.reset();
DestroyCalls();
if (num_audio_streams_ > 0)
DestroyVoiceEngines();
});
}
@ -219,10 +215,8 @@ void CallTest::CreateAudioAndFecSendConfigs(size_t num_audio_streams,
Transport* send_transport) {
RTC_DCHECK_LE(num_audio_streams, 1);
RTC_DCHECK_LE(num_flexfec_streams, 1);
RTC_DCHECK(num_audio_streams == 0 || voe_send_.channel_id >= 0);
if (num_audio_streams > 0) {
audio_send_config_ = AudioSendStream::Config(send_transport);
audio_send_config_.voe_channel_id = voe_send_.channel_id;
audio_send_config_.rtp.ssrc = kAudioSendSsrc;
audio_send_config_.send_codec_spec =
rtc::Optional<AudioSendStream::Config::SendCodecSpec>(
@ -281,11 +275,9 @@ void CallTest::CreateMatchingAudioAndFecConfigs(
Transport* rtcp_send_transport) {
RTC_DCHECK_GE(1, num_audio_streams_);
if (num_audio_streams_ == 1) {
RTC_DCHECK_LE(0, voe_send_.channel_id);
AudioReceiveStream::Config audio_config;
audio_config.rtp.local_ssrc = kReceiverLocalAudioSsrc;
audio_config.rtcp_send_transport = rtcp_send_transport;
audio_config.voe_channel_id = voe_recv_.channel_id;
audio_config.rtp.remote_ssrc = audio_send_config_.rtp.ssrc;
audio_config.decoder_factory = decoder_factory_;
audio_config.decoder_map = {{kAudioSendPayloadType, {"opus", 48000, 2}}};
@ -457,43 +449,6 @@ void CallTest::SetFakeVideoCaptureRotation(VideoRotation rotation) {
frame_generator_capturer_->SetFakeRotation(rotation);
}
void CallTest::CreateVoiceEngines() {
voe_send_.voice_engine = VoiceEngine::Create();
voe_send_.base = VoEBase::GetInterface(voe_send_.voice_engine);
EXPECT_EQ(0, fake_send_audio_device_->Init());
EXPECT_EQ(0, voe_send_.base->Init(fake_send_audio_device_.get(),
nullptr, decoder_factory_));
VoEBase::ChannelConfig config;
config.enable_voice_pacing = true;
voe_send_.channel_id = voe_send_.base->CreateChannel(config);
EXPECT_GE(voe_send_.channel_id, 0);
voe_recv_.voice_engine = VoiceEngine::Create();
voe_recv_.base = VoEBase::GetInterface(voe_recv_.voice_engine);
EXPECT_EQ(0, fake_recv_audio_device_->Init());
EXPECT_EQ(0, voe_recv_.base->Init(fake_recv_audio_device_.get(),
nullptr, decoder_factory_));
voe_recv_.channel_id = voe_recv_.base->CreateChannel();
EXPECT_GE(voe_recv_.channel_id, 0);
}
void CallTest::DestroyVoiceEngines() {
voe_recv_.base->DeleteChannel(voe_recv_.channel_id);
voe_recv_.channel_id = -1;
voe_recv_.base->Release();
voe_recv_.base = nullptr;
voe_send_.base->DeleteChannel(voe_send_.channel_id);
voe_send_.channel_id = -1;
voe_send_.base->Release();
voe_send_.base = nullptr;
VoiceEngine::Delete(voe_send_.voice_engine);
voe_send_.voice_engine = nullptr;
VoiceEngine::Delete(voe_recv_.voice_engine);
voe_recv_.voice_engine = nullptr;
}
constexpr size_t CallTest::kNumSsrcs;
const int CallTest::kDefaultWidth;
const int CallTest::kDefaultHeight;

View File

@ -26,9 +26,6 @@
#include "test/single_threaded_task_queue.h"
namespace webrtc {
class VoEBase;
namespace test {
class BaseTest;
@ -67,9 +64,8 @@ class CallTest : public ::testing::Test {
static const std::map<uint8_t, MediaType> payload_type_map_;
protected:
// RunBaseTest overwrites the audio_state and the voice_engine of the send and
// receive Call configs to simplify test code and avoid having old VoiceEngine
// APIs in the tests.
// RunBaseTest overwrites the audio_state of the send and receive Call configs
// to simplify test code.
void RunBaseTest(BaseTest* test);
void CreateCalls(const Call::Config& sender_config,
@ -152,25 +148,6 @@ class CallTest : public ::testing::Test {
SingleThreadedTaskQueueForTesting task_queue_;
private:
// TODO(holmer): Remove once VoiceEngine is fully refactored to the new API.
// These methods are used to set up legacy voice engines and channels which is
// necessary while voice engine is being refactored to the new stream API.
struct VoiceEngineState {
VoiceEngineState()
: voice_engine(nullptr),
base(nullptr),
channel_id(-1) {}
VoiceEngine* voice_engine;
VoEBase* base;
int channel_id;
};
void CreateVoiceEngines();
void DestroyVoiceEngines();
VoiceEngineState voe_send_;
VoiceEngineState voe_recv_;
rtc::scoped_refptr<AudioProcessing> apm_send_;
rtc::scoped_refptr<AudioProcessing> apm_recv_;
rtc::scoped_refptr<test::FakeAudioDevice> fake_send_audio_device_;

View File

@ -62,14 +62,11 @@ class MockVoEChannelProxy : public voe::ChannelProxy {
int payload_frequency));
MOCK_METHOD2(SendTelephoneEventOutband, bool(int event, int duration_ms));
MOCK_METHOD2(SetBitrate, void(int bitrate_bps, int64_t probing_interval_ms));
// TODO(solenberg): Talk the compiler into accepting this mock method:
// MOCK_METHOD1(SetSink, void(std::unique_ptr<AudioSinkInterface> sink));
MOCK_METHOD1(SetSink, void(AudioSinkInterface* sink));
MOCK_METHOD1(SetInputMute, void(bool muted));
MOCK_METHOD1(RegisterTransport, void(Transport* transport));
MOCK_METHOD1(OnRtpPacket, void(const RtpPacketReceived& packet));
MOCK_METHOD2(ReceivedRTCPPacket, bool(const uint8_t* packet, size_t length));
MOCK_CONST_METHOD0(GetAudioDecoderFactory,
const rtc::scoped_refptr<AudioDecoderFactory>&());
MOCK_METHOD1(SetChannelOutputVolumeScaling, void(float scaling));
MOCK_METHOD1(SetRtcEventLog, void(RtcEventLog* event_log));
MOCK_METHOD1(SetRtcpRttStats, void(RtcpRttStats* rtcp_rtt_stats));

View File

@ -1,108 +0,0 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef AUDIO_MOCK_VOICE_ENGINE_H_
#define AUDIO_MOCK_VOICE_ENGINE_H_
#include <memory>
#include "modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
#include "test/gmock.h"
#include "test/mock_voe_channel_proxy.h"
#include "voice_engine/voice_engine_impl.h"
namespace webrtc {
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 : public VoiceEngineImpl {
public:
// TODO(nisse): Valid overrides commented out, because the gmock
// methods don't use any override declarations, and we want to avoid
// warnings from -Winconsistent-missing-override. See
// http://crbug.com/428099.
MockVoiceEngine(
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory = nullptr)
: decoder_factory_(decoder_factory) {
// Increase ref count so this object isn't automatically deleted whenever
// interfaces are Release():d.
++_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 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::_))
.WillByDefault(testing::Invoke([this](int channel_id) {
auto* proxy =
new testing::NiceMock<webrtc::test::MockVoEChannelProxy>();
EXPECT_CALL(*proxy, GetAudioDecoderFactory())
.WillRepeatedly(testing::ReturnRef(decoder_factory_));
EXPECT_CALL(*proxy, SetReceiveCodecs(testing::_))
.WillRepeatedly(testing::Invoke(
[](const std::map<int, SdpAudioFormat>& codecs) {
EXPECT_THAT(codecs, testing::IsEmpty());
}));
EXPECT_CALL(*proxy, GetRtpRtcp(testing::_, testing::_))
.WillRepeatedly(
testing::SetArgPointee<0>(GetMockRtpRtcp(channel_id)));
return proxy;
}));
}
virtual ~MockVoiceEngine() /* override */ {
// Decrease ref count before base class d-tor is called; otherwise it will
// trigger an assertion.
--_ref_count;
}
// These need to be the same each call to channel_id and must not leak.
MockRtpRtcp* GetMockRtpRtcp(int channel_id) {
if (mock_rtp_rtcps_.find(channel_id) == mock_rtp_rtcps_.end()) {
mock_rtp_rtcps_[channel_id].reset(new ::testing::NiceMock<MockRtpRtcp>);
}
return mock_rtp_rtcps_[channel_id].get();
}
// Allows injecting a ChannelProxy factory.
MOCK_METHOD1(ChannelProxyFactory, voe::ChannelProxy*(int channel_id));
// VoiceEngineImpl
virtual std::unique_ptr<voe::ChannelProxy> GetChannelProxy(
int channel_id) /* override */ {
return std::unique_ptr<voe::ChannelProxy>(ChannelProxyFactory(channel_id));
}
// VoEBase
MOCK_METHOD3(
Init,
int(AudioDeviceModule* external_adm,
AudioProcessing* external_apm,
const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory));
MOCK_METHOD0(Terminate, void());
MOCK_METHOD0(CreateChannel, int());
MOCK_METHOD1(CreateChannel, int(const ChannelConfig& config));
MOCK_METHOD1(DeleteChannel, int(int channel));
private:
// TODO(ossu): I'm not particularly happy about keeping the decoder factory
// here, but due to how gmock is implemented, I cannot just keep it in the
// functor implementing the default version of ChannelProxyFactory, above.
// GMock creates an unfortunate copy of the functor, which would cause us to
// return a dangling reference. Fortunately, this should go away once
// voe::Channel does.
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory_;
std::map<int, std::unique_ptr<MockRtpRtcp>> mock_rtp_rtcps_;
};
} // namespace test
} // namespace webrtc
#endif // AUDIO_MOCK_VOICE_ENGINE_H_

View File

@ -41,7 +41,6 @@
#include "test/testsupport/test_artifacts.h"
#include "test/vcm_capturer.h"
#include "test/video_renderer.h"
#include "voice_engine/include/voe_base.h"
DEFINE_bool(save_worst_frame,
false,
@ -62,47 +61,6 @@ constexpr uint32_t kThumbnailRtxSsrcStart = 0xF0000;
constexpr int kDefaultMaxQp = cricket::WebRtcVideoChannel::kDefaultQpMax;
struct VoiceEngineState {
VoiceEngineState()
: voice_engine(nullptr),
base(nullptr),
send_channel_id(-1),
receive_channel_id(-1) {}
webrtc::VoiceEngine* voice_engine;
webrtc::VoEBase* base;
int send_channel_id;
int receive_channel_id;
};
void CreateVoiceEngine(
VoiceEngineState* voe,
webrtc::AudioDeviceModule* adm,
rtc::scoped_refptr<webrtc::AudioDecoderFactory> decoder_factory) {
voe->voice_engine = webrtc::VoiceEngine::Create();
voe->base = webrtc::VoEBase::GetInterface(voe->voice_engine);
EXPECT_EQ(0, adm->Init());
EXPECT_EQ(0, voe->base->Init(adm, nullptr, decoder_factory));
webrtc::VoEBase::ChannelConfig config;
config.enable_voice_pacing = true;
voe->send_channel_id = voe->base->CreateChannel(config);
EXPECT_GE(voe->send_channel_id, 0);
voe->receive_channel_id = voe->base->CreateChannel();
EXPECT_GE(voe->receive_channel_id, 0);
}
void DestroyVoiceEngine(VoiceEngineState* voe) {
voe->base->DeleteChannel(voe->send_channel_id);
voe->send_channel_id = -1;
voe->base->DeleteChannel(voe->receive_channel_id);
voe->receive_channel_id = -1;
voe->base->Release();
voe->base = nullptr;
webrtc::VoiceEngine::Delete(voe->voice_engine);
voe->voice_engine = nullptr;
}
class VideoStreamFactory
: public webrtc::VideoEncoderConfig::VideoStreamFactoryInterface {
public:
@ -2023,12 +1981,9 @@ void VideoQualityTest::RunWithAnalyzer(const Params& params) {
});
}
void VideoQualityTest::SetupAudio(int send_channel_id,
int receive_channel_id,
Transport* transport,
void VideoQualityTest::SetupAudio(Transport* transport,
AudioReceiveStream** audio_receive_stream) {
audio_send_config_ = AudioSendStream::Config(transport);
audio_send_config_.voe_channel_id = send_channel_id;
audio_send_config_.rtp.ssrc = kAudioSendSsrc;
// Add extension to enable audio send side BWE, and allow audio bit rate
@ -2052,7 +2007,6 @@ void VideoQualityTest::SetupAudio(int send_channel_id,
AudioReceiveStream::Config audio_config;
audio_config.rtp.local_ssrc = kReceiverLocalAudioSsrc;
audio_config.rtcp_send_transport = transport;
audio_config.voe_channel_id = receive_channel_id;
audio_config.rtp.remote_ssrc = audio_send_config_.rtp.ssrc;
audio_config.rtp.transport_cc = params_.call.send_side_bwe;
audio_config.rtp.extensions = audio_send_config_.rtp.extensions;
@ -2069,7 +2023,6 @@ void VideoQualityTest::RunWithRenderers(const Params& params) {
num_video_streams_ = params.call.dual_video ? 2 : 1;
std::unique_ptr<test::LayerFilteringTransport> send_transport;
std::unique_ptr<test::DirectTransport> recv_transport;
::VoiceEngineState voe;
std::unique_ptr<test::VideoRenderer> local_preview;
std::vector<std::unique_ptr<test::VideoRenderer>> loopback_renderers;
AudioReceiveStream* audio_receive_stream = nullptr;
@ -2090,9 +2043,7 @@ void VideoQualityTest::RunWithRenderers(const Params& params) {
1.f);
if (params_.audio.enabled) {
CreateVoiceEngine(&voe, fake_audio_device.get(), decoder_factory_);
AudioState::Config audio_state_config;
audio_state_config.voice_engine = voe.voice_engine;
audio_state_config.audio_mixer = AudioMixerImpl::Create();
audio_state_config.audio_processing = AudioProcessingBuilder().Create();
audio_state_config.audio_device_module = fake_audio_device;
@ -2168,8 +2119,7 @@ void VideoQualityTest::RunWithRenderers(const Params& params) {
}
if (params_.audio.enabled) {
SetupAudio(voe.send_channel_id, voe.receive_channel_id,
send_transport.get(), &audio_receive_stream);
SetupAudio(send_transport.get(), &audio_receive_stream);
}
for (VideoReceiveStream* receive_stream : video_receive_streams_)
@ -2219,9 +2169,6 @@ void VideoQualityTest::RunWithRenderers(const Params& params) {
send_transport.reset();
recv_transport.reset();
if (params_.audio.enabled)
DestroyVoiceEngine(&voe);
local_preview.reset();
loopback_renderers.clear();

View File

@ -134,9 +134,7 @@ class VideoQualityTest : public test::CallTest {
void SetupVideo(Transport* send_transport, Transport* recv_transport);
void SetupThumbnails(Transport* send_transport, Transport* recv_transport);
void DestroyThumbnailStreams();
void SetupAudio(int send_channel_id,
int receive_channel_id,
Transport* transport,
void SetupAudio(Transport* transport,
AudioReceiveStream** audio_receive_stream);
void StartEncodedFrameLogs(VideoSendStream* stream);

View File

@ -15,14 +15,10 @@ rtc_static_library("voice_engine") {
sources = [
"channel.cc",
"channel.h",
"channel_manager.cc",
"channel_manager.h",
"channel_proxy.cc",
"channel_proxy.h",
"include/voe_base.h",
"include/voe_errors.h",
"shared_data.cc",
"shared_data.h",
"transport_feedback_packet_loss_tracker.cc",
"transport_feedback_packet_loss_tracker.h",
"utility.cc",
@ -134,10 +130,8 @@ if (rtc_include_tests) {
}
sources = [
"channel_unittest.cc",
"transport_feedback_packet_loss_tracker_unittest.cc",
"utility_unittest.cc",
"voe_base_unittest.cc",
]
data = [

View File

@ -574,24 +574,24 @@ int Channel::PreferredSampleRate() const {
audio_coding_->PlayoutFrequency());
}
int32_t Channel::CreateChannel(Channel*& channel,
int32_t channelId,
uint32_t instanceId,
const VoEBase::ChannelConfig& config) {
channel = new Channel(channelId, instanceId, config);
if (channel == NULL) {
RTC_LOG(LS_ERROR) << "unable to allocate memory for new channel";
return -1;
}
return 0;
Channel::Channel(rtc::TaskQueue* encoder_queue,
ProcessThread* module_process_thread,
AudioDeviceModule* audio_device_module)
: Channel(module_process_thread,
audio_device_module,
0,
false,
rtc::scoped_refptr<AudioDecoderFactory>()) {
RTC_DCHECK(encoder_queue);
encoder_queue_ = encoder_queue;
}
Channel::Channel(int32_t channelId,
uint32_t instanceId,
const VoEBase::ChannelConfig& config)
: _instanceId(instanceId),
_channelId(channelId),
event_log_proxy_(new RtcEventLogProxy()),
Channel::Channel(ProcessThread* module_process_thread,
AudioDeviceModule* audio_device_module,
size_t jitter_buffer_max_packets,
bool jitter_buffer_fast_playout,
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory)
: event_log_proxy_(new RtcEventLogProxy()),
rtcp_rtt_stats_proxy_(new RtcpRttStatsProxy()),
rtp_header_parser_(RtpHeaderParser::Create()),
rtp_payload_registry_(new RTPPayloadRegistry()),
@ -613,8 +613,8 @@ Channel::Channel(int32_t channelId,
rtp_ts_wraparound_handler_(new rtc::TimestampWrapAroundHandler()),
capture_start_rtp_time_stamp_(-1),
capture_start_ntp_time_ms_(-1),
_moduleProcessThreadPtr(NULL),
_audioDeviceModulePtr(NULL),
_moduleProcessThreadPtr(module_process_thread),
_audioDeviceModulePtr(audio_device_module),
_transportPtr(NULL),
input_mute_(false),
previous_frame_muted_(false),
@ -623,17 +623,20 @@ Channel::Channel(int32_t channelId,
transport_overhead_per_packet_(0),
rtp_overhead_per_packet_(0),
rtcp_observer_(new VoERtcpObserver(this)),
associate_send_channel_(ChannelOwner(nullptr)),
pacing_enabled_(config.enable_voice_pacing),
associated_send_channel_(nullptr),
feedback_observer_proxy_(new TransportFeedbackProxy()),
seq_num_allocator_proxy_(new TransportSequenceNumberProxy()),
rtp_packet_sender_proxy_(new RtpPacketSenderProxy()),
retransmission_rate_limiter_(new RateLimiter(Clock::GetRealTimeClock(),
kMaxRetransmissionWindowMs)),
decoder_factory_(config.acm_config.decoder_factory),
use_twcc_plr_for_ana_(
webrtc::field_trial::FindFullName("UseTwccPlrForAna") == "Enabled") {
AudioCodingModule::Config acm_config(config.acm_config);
RTC_DCHECK(module_process_thread);
RTC_DCHECK(audio_device_module);
AudioCodingModule::Config acm_config;
acm_config.decoder_factory = decoder_factory;
acm_config.neteq_config.max_packets_in_buffer = jitter_buffer_max_packets;
acm_config.neteq_config.enable_fast_accelerate = jitter_buffer_fast_playout;
acm_config.neteq_config.enable_muted_state = true;
audio_coding_.reset(AudioCodingModule::Create(acm_config));
@ -658,36 +661,25 @@ Channel::Channel(int32_t channelId,
_rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration));
_rtpRtcpModule->SetSendingMediaStatus(false);
Init();
}
Channel::~Channel() {
Terminate();
RTC_DCHECK(!channel_state_.Get().sending);
RTC_DCHECK(!channel_state_.Get().playing);
}
int32_t Channel::Init() {
RTC_DCHECK(construction_thread_.CalledOnValidThread());
void Channel::Init() {
channel_state_.Reset();
// --- Initial sanity
if (_moduleProcessThreadPtr == NULL) {
RTC_LOG(LS_ERROR)
<< "Channel::Init() must call SetEngineInformation() first";
return -1;
}
// --- Add modules to process thread (for periodic schedulation)
_moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get(), RTC_FROM_HERE);
// --- ACM initialization
if (audio_coding_->InitializeReceiver() == -1) {
RTC_LOG(LS_ERROR) << "Channel::Init() unable to initialize the ACM - 1";
return -1;
}
int error = audio_coding_->InitializeReceiver();
RTC_DCHECK_EQ(0, error);
// --- RTP/RTCP module initialization
@ -699,13 +691,10 @@ int32_t Channel::Init() {
telephone_event_handler_->SetTelephoneEventForwardToDecoder(true);
// RTCP is enabled by default.
_rtpRtcpModule->SetRTCPStatus(RtcpMode::kCompound);
// --- Register all permanent callbacks
if (audio_coding_->RegisterTransportCallback(this) == -1) {
RTC_LOG(LS_ERROR) << "Channel::Init() callbacks not registered";
return -1;
}
return 0;
// --- Register all permanent callbacks
error = audio_coding_->RegisterTransportCallback(this);
RTC_DCHECK_EQ(0, error);
}
void Channel::Terminate() {
@ -720,11 +709,8 @@ void Channel::Terminate() {
// 1. De-register callbacks in modules
// 2. De-register modules in process thread
// 3. Destroy modules
if (audio_coding_->RegisterTransportCallback(NULL) == -1) {
RTC_LOG(LS_WARNING)
<< "Terminate() failed to de-register transport callback"
<< " (Audio coding module)";
}
int error = audio_coding_->RegisterTransportCallback(NULL);
RTC_DCHECK_EQ(0, error);
// De-register modules in process thread
if (_moduleProcessThreadPtr)
@ -733,25 +719,9 @@ void Channel::Terminate() {
// End of modules shutdown
}
int32_t Channel::SetEngineInformation(ProcessThread& moduleProcessThread,
AudioDeviceModule& audioDeviceModule,
rtc::TaskQueue* encoder_queue) {
RTC_DCHECK(encoder_queue);
RTC_DCHECK(!encoder_queue_);
_moduleProcessThreadPtr = &moduleProcessThread;
_audioDeviceModulePtr = &audioDeviceModule;
encoder_queue_ = encoder_queue;
return 0;
}
void Channel::SetSink(std::unique_ptr<AudioSinkInterface> sink) {
void Channel::SetSink(AudioSinkInterface* sink) {
rtc::CritScope cs(&_callbackCritSect);
audio_sink_ = std::move(sink);
}
const rtc::scoped_refptr<AudioDecoderFactory>&
Channel::GetAudioDecoderFactory() const {
return decoder_factory_;
audio_sink_ = sink;
}
int32_t Channel::StartPlayout() {
@ -1387,29 +1357,17 @@ void Channel::ProcessAndEncodeAudioOnTaskQueue(AudioFrame* audio_input) {
// is done and payload is ready for packetization and transmission.
// Otherwise, it will return without invoking the callback.
if (audio_coding_->Add10MsData(*audio_input) < 0) {
RTC_LOG(LS_ERROR) << "ACM::Add10MsData() failed for channel " << _channelId;
RTC_LOG(LS_ERROR) << "ACM::Add10MsData() failed.";
return;
}
_timeStamp += static_cast<uint32_t>(audio_input->samples_per_channel_);
}
void Channel::set_associate_send_channel(const ChannelOwner& channel) {
RTC_DCHECK(!channel.channel() ||
channel.channel()->ChannelId() != _channelId);
void Channel::SetAssociatedSendChannel(Channel* channel) {
RTC_DCHECK_NE(this, channel);
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();
if (channel && channel->ChannelId() == channel_id) {
// If this channel is associated with a send channel of the specified
// Channel ID, disassociate with it.
ChannelOwner ref(NULL);
associate_send_channel_ = ref;
}
associated_send_channel_ = channel;
}
void Channel::SetRtcEventLog(RtcEventLog* event_log) {
@ -1526,25 +1484,6 @@ void Channel::UpdatePlayoutTimestamp(bool rtcp) {
}
}
void Channel::RegisterReceiveCodecsToRTPModule() {
// TODO(kwiberg): Iterate over the factory's supported codecs instead?
const int nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
for (int idx = 0; idx < nSupportedCodecs; idx++) {
CodecInst codec;
if (audio_coding_->Codec(idx, &codec) == -1) {
RTC_LOG(LS_WARNING) << "Unable to register codec #" << idx
<< " for RTP/RTCP receiver.";
continue;
}
const SdpAudioFormat format = CodecInstToSdp(codec);
if (!decoder_factory_->IsSupportedDecoder(format) ||
rtp_receiver_->RegisterReceivePayload(codec.pltype, format) == -1) {
RTC_LOG(LS_WARNING) << "Unable to register " << format
<< " for RTP/RTCP receiver.";
}
}
}
int Channel::SetSendRtpHeaderExtension(bool enable,
RTPExtensionType type,
unsigned char id) {
@ -1579,14 +1518,13 @@ int64_t Channel::GetRTT(bool allow_associate_channel) const {
if (report_blocks.empty()) {
if (allow_associate_channel) {
rtc::CritScope lock(&assoc_send_channel_lock_);
Channel* channel = associate_send_channel_.channel();
// Tries to get RTT from an associated channel. This is important for
// receive-only channels.
if (channel) {
if (associated_send_channel_) {
// To prevent infinite recursion and deadlock, calling GetRTT of
// associate channel should always use "false" for argument:
// |allow_associate_channel|.
rtt = channel->GetRTT(false);
rtt = associated_send_channel_->GetRTT(false);
}
}
return rtt;

View File

@ -27,10 +27,9 @@
#include "modules/rtp_rtcp/include/rtp_rtcp.h"
#include "rtc_base/criticalsection.h"
#include "rtc_base/event.h"
#include "rtc_base/task_queue.h"
#include "rtc_base/thread_checker.h"
#include "voice_engine/audio_level.h"
#include "voice_engine/include/voe_base.h"
#include "voice_engine/shared_data.h"
namespace rtc {
class TimestampWrapAroundHandler;
@ -142,27 +141,19 @@ class Channel
enum { KNumSocketThreads = 1 };
enum { KNumberOfSocketBuffers = 8 };
// Used for send streams.
Channel(rtc::TaskQueue* encoder_queue,
ProcessThread* module_process_thread,
AudioDeviceModule* audio_device_module);
// Used for receive streams.
Channel(ProcessThread* module_process_thread,
AudioDeviceModule* audio_device_module,
size_t jitter_buffer_max_packets,
bool jitter_buffer_fast_playout,
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory);
virtual ~Channel();
static int32_t CreateChannel(Channel*& channel,
int32_t channelId,
uint32_t instanceId,
const VoEBase::ChannelConfig& config);
Channel(int32_t channelId,
uint32_t instanceId,
const VoEBase::ChannelConfig& config);
int32_t Init();
void Terminate();
int32_t SetEngineInformation(ProcessThread& moduleProcessThread,
AudioDeviceModule& audioDeviceModule,
rtc::TaskQueue* encoder_queue);
void SetSink(std::unique_ptr<AudioSinkInterface> sink);
// TODO(ossu): Don't use! It's only here to confirm that the decoder factory
// passed into AudioReceiveStream is the same as the one set when creating the
// ADM. Once Channel creation is moved into Audio{Send,Receive}Stream this can
// go.
const rtc::scoped_refptr<AudioDecoderFactory>& GetAudioDecoderFactory() const;
void SetSink(AudioSinkInterface* sink);
void SetReceiveCodecs(const std::map<int, SdpAudioFormat>& codecs);
@ -270,8 +261,6 @@ class Channel
int PreferredSampleRate() const;
uint32_t InstanceId() const { return _instanceId; }
int32_t ChannelId() const { return _channelId; }
bool Playing() const { return channel_state_.Get().playing; }
bool Sending() const { return channel_state_.Get().sending; }
RtpRtcp* RtpRtcpModulePtr() const { return _rtpRtcpModule.get(); }
@ -290,9 +279,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);
// Disassociate a send channel if it was associated.
void DisassociateSendChannel(int channel_id);
void SetAssociatedSendChannel(Channel* channel);
// Set a RtcEventLog logging object.
void SetRtcEventLog(RtcEventLog* event_log);
@ -318,6 +305,9 @@ class Channel
private:
class ProcessAndEncodeAudioTask;
void Init();
void Terminate();
int GetRemoteSSRC(unsigned int& ssrc);
void OnUplinkPacketLossRate(float packet_loss_rate);
bool InputMute() const;
@ -330,7 +320,6 @@ class Channel
bool IsPacketRetransmitted(const RTPHeader& header, bool in_order) const;
int ResendPackets(const uint16_t* sequence_numbers, int length);
void UpdatePlayoutTimestamp(bool rtcp);
void RegisterReceiveCodecsToRTPModule();
int SetSendRtpHeaderExtension(bool enable,
RTPExtensionType type,
@ -346,9 +335,6 @@ class Channel
// for encoding.
void ProcessAndEncodeAudioOnTaskQueue(AudioFrame* audio_input);
uint32_t _instanceId;
int32_t _channelId;
rtc::CriticalSection _callbackCritSect;
rtc::CriticalSection volume_settings_critsect_;
@ -364,7 +350,7 @@ class Channel
TelephoneEventHandler* telephone_event_handler_;
std::unique_ptr<RtpRtcp> _rtpRtcpModule;
std::unique_ptr<AudioCodingModule> audio_coding_;
std::unique_ptr<AudioSinkInterface> audio_sink_;
AudioSinkInterface* audio_sink_ = nullptr;
AudioLevel _outputAudioLevel;
uint32_t _timeStamp RTC_ACCESS_ON(encoder_queue_);
@ -407,26 +393,21 @@ class Channel
std::unique_ptr<VoERtcpObserver> rtcp_observer_;
// An associated send channel.
rtc::CriticalSection assoc_send_channel_lock_;
ChannelOwner associate_send_channel_ RTC_GUARDED_BY(assoc_send_channel_lock_);
Channel* associated_send_channel_ RTC_GUARDED_BY(assoc_send_channel_lock_);
bool pacing_enabled_;
bool pacing_enabled_ = true;
PacketRouter* packet_router_ = nullptr;
std::unique_ptr<TransportFeedbackProxy> feedback_observer_proxy_;
std::unique_ptr<TransportSequenceNumberProxy> seq_num_allocator_proxy_;
std::unique_ptr<RtpPacketSenderProxy> rtp_packet_sender_proxy_;
std::unique_ptr<RateLimiter> retransmission_rate_limiter_;
// TODO(ossu): Remove once GetAudioDecoderFactory() is no longer needed.
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory_;
rtc::ThreadChecker construction_thread_;
const bool use_twcc_plr_for_ana_;
rtc::CriticalSection encoder_queue_lock_;
bool encoder_queue_is_active_ RTC_GUARDED_BY(encoder_queue_lock_) = false;
rtc::TaskQueue* encoder_queue_ = nullptr;
};

View File

@ -1,134 +0,0 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "voice_engine/channel_manager.h"
#include "rtc_base/timeutils.h"
#include "voice_engine/channel.h"
namespace webrtc {
namespace voe {
ChannelOwner::ChannelOwner(class Channel* channel)
: channel_ref_(new ChannelRef(channel)) {}
ChannelOwner::ChannelRef::ChannelRef(class Channel* channel)
: channel(channel) {}
ChannelManager::ChannelManager(uint32_t instance_id)
: instance_id_(instance_id),
last_channel_id_(-1),
random_(rtc::TimeNanos()) {}
ChannelOwner ChannelManager::CreateChannel(
const VoEBase::ChannelConfig& config) {
Channel* channel;
Channel::CreateChannel(channel, ++last_channel_id_, instance_id_, config);
// TODO(solenberg): Delete this, users should configure ssrc
// explicitly.
channel->SetLocalSSRC(random_.Rand<uint32_t>());
ChannelOwner channel_owner(channel);
rtc::CritScope crit(&lock_);
channels_.push_back(channel_owner);
return channel_owner;
}
ChannelOwner ChannelManager::GetChannel(int32_t channel_id) {
rtc::CritScope crit(&lock_);
for (size_t i = 0; i < channels_.size(); ++i) {
if (channels_[i].channel()->ChannelId() == channel_id)
return channels_[i];
}
return ChannelOwner(NULL);
}
void ChannelManager::GetAllChannels(std::vector<ChannelOwner>* channels) {
rtc::CritScope crit(&lock_);
*channels = channels_;
}
void ChannelManager::DestroyChannel(int32_t channel_id) {
assert(channel_id >= 0);
// Holds a reference to a channel, this is used so that we never delete
// Channels while holding a lock, but rather when the method returns.
ChannelOwner reference(NULL);
{
rtc::CritScope crit(&lock_);
std::vector<ChannelOwner>::iterator to_delete = channels_.end();
for (auto it = channels_.begin(); it != channels_.end(); ++it) {
Channel* channel = it->channel();
// For channels associated with the channel to be deleted, disassociate
// with that channel.
channel->DisassociateSendChannel(channel_id);
if (channel->ChannelId() == channel_id) {
to_delete = it;
}
}
if (to_delete != channels_.end()) {
reference = *to_delete;
channels_.erase(to_delete);
}
}
if (reference.channel()) {
// Ensure the channel is torn down now, on this thread, since a reference
// may still be held on a different thread (e.g. in the audio capture
// thread).
reference.channel()->Terminate();
}
}
void ChannelManager::DestroyAllChannels() {
// Holds references so that Channels are not destroyed while holding this
// lock, but rather when the method returns.
std::vector<ChannelOwner> references;
{
rtc::CritScope crit(&lock_);
references = channels_;
channels_.clear();
}
for (auto& owner : references) {
if (owner.channel())
owner.channel()->Terminate();
}
}
size_t ChannelManager::NumOfChannels() const {
rtc::CritScope crit(&lock_);
return channels_.size();
}
ChannelManager::Iterator::Iterator(ChannelManager* channel_manager)
: iterator_pos_(0) {
channel_manager->GetAllChannels(&channels_);
}
Channel* ChannelManager::Iterator::GetChannel() {
if (iterator_pos_ < channels_.size())
return channels_[iterator_pos_].channel();
return NULL;
}
bool ChannelManager::Iterator::IsValid() {
return iterator_pos_ < channels_.size();
}
void ChannelManager::Iterator::Increment() {
++iterator_pos_;
}
} // namespace voe
} // namespace webrtc

View File

@ -1,127 +0,0 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VOICE_ENGINE_CHANNEL_MANAGER_H_
#define VOICE_ENGINE_CHANNEL_MANAGER_H_
#include <memory>
#include <vector>
#include "api/refcountedbase.h"
#include "rtc_base/constructormagic.h"
#include "rtc_base/criticalsection.h"
#include "rtc_base/random.h"
#include "rtc_base/scoped_ref_ptr.h"
#include "system_wrappers/include/atomic32.h"
#include "typedefs.h" // NOLINT(build/include)
#include "voice_engine/include/voe_base.h"
namespace webrtc {
class AudioDecoderFactory;
namespace voe {
class Channel;
// Shared-pointer implementation for keeping track of Channels. The underlying
// shared instance will be dropped when no more ChannelOwners point to it.
//
// One common source of ChannelOwner instances are
// ChannelManager::CreateChannel() and ChannelManager::GetChannel(...).
// It has a similar use case to shared_ptr in C++11. Should this move to C++11
// in the future, this class should be replaced by exactly that.
//
// To access the underlying Channel, use .channel().
// IsValid() implements a convenience method as an alternative for checking
// whether the underlying pointer is NULL or not.
//
// Channel channel_owner = channel_manager.GetChannel(channel_id);
// if (channel_owner.IsValid())
// channel_owner.channel()->...;
//
class ChannelOwner {
public:
explicit ChannelOwner(Channel* channel);
ChannelOwner(const ChannelOwner& channel_owner) = default;
~ChannelOwner() = default;
ChannelOwner& operator=(const ChannelOwner& other) = default;
Channel* channel() const { return channel_ref_->channel.get(); }
bool IsValid() { return channel_ref_->channel.get() != NULL; }
private:
// Shared instance of a Channel. Copying ChannelOwners increase the reference
// count and destroying ChannelOwners decrease references. Channels are
// deleted when no references to them are held.
struct ChannelRef : public rtc::RefCountedBase {
ChannelRef(Channel* channel);
const std::unique_ptr<Channel> channel;
};
rtc::scoped_refptr<ChannelRef> channel_ref_;
};
class ChannelManager {
public:
ChannelManager(uint32_t instance_id);
// Upon construction of an Iterator it will grab a copy of the channel list of
// the ChannelManager. The iteration will then occur over this state, not the
// current one of the ChannelManager. As the Iterator holds its own references
// to the Channels, they will remain valid even if they are removed from the
// ChannelManager.
class Iterator {
public:
explicit Iterator(ChannelManager* channel_manager);
Channel* GetChannel();
bool IsValid();
void Increment();
private:
size_t iterator_pos_;
std::vector<ChannelOwner> channels_;
RTC_DISALLOW_COPY_AND_ASSIGN(Iterator);
};
// CreateChannel will always return a valid ChannelOwner instance.
ChannelOwner CreateChannel(const VoEBase::ChannelConfig& config);
// ChannelOwner.channel() will be NULL if channel_id is invalid or no longer
// exists. This should be checked with ChannelOwner::IsValid().
ChannelOwner GetChannel(int32_t channel_id);
void GetAllChannels(std::vector<ChannelOwner>* channels);
void DestroyChannel(int32_t channel_id);
void DestroyAllChannels();
size_t NumOfChannels() const;
private:
uint32_t instance_id_;
Atomic32 last_channel_id_;
rtc::CriticalSection lock_;
std::vector<ChannelOwner> channels_;
// For generation of random ssrc:s.
webrtc::Random random_;
RTC_DISALLOW_COPY_AND_ASSIGN(ChannelManager);
};
} // namespace voe
} // namespace webrtc
#endif // VOICE_ENGINE_CHANNEL_MANAGER_H_

View File

@ -17,15 +17,14 @@
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_minmax.h"
#include "voice_engine/channel.h"
namespace webrtc {
namespace voe {
ChannelProxy::ChannelProxy() : channel_owner_(nullptr) {}
ChannelProxy::ChannelProxy() {}
ChannelProxy::ChannelProxy(const ChannelOwner& channel_owner) :
channel_owner_(channel_owner) {
RTC_CHECK(channel_owner_.channel());
ChannelProxy::ChannelProxy(std::unique_ptr<Channel> channel) :
channel_(std::move(channel)) {
RTC_DCHECK(channel_);
module_process_thread_checker_.DetachFromThread();
}
@ -34,23 +33,23 @@ ChannelProxy::~ChannelProxy() {}
bool ChannelProxy::SetEncoder(int payload_type,
std::unique_ptr<AudioEncoder> encoder) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return channel()->SetEncoder(payload_type, std::move(encoder));
return channel_->SetEncoder(payload_type, std::move(encoder));
}
void ChannelProxy::ModifyEncoder(
rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)> modifier) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->ModifyEncoder(modifier);
channel_->ModifyEncoder(modifier);
}
void ChannelProxy::SetRTCPStatus(bool enable) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->SetRTCPStatus(enable);
channel_->SetRTCPStatus(enable);
}
void ChannelProxy::SetLocalSSRC(uint32_t ssrc) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
int error = channel()->SetLocalSSRC(ssrc);
int error = channel_->SetLocalSSRC(ssrc);
RTC_DCHECK_EQ(0, error);
}
@ -58,65 +57,65 @@ void ChannelProxy::SetRTCP_CNAME(const std::string& c_name) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
// Note: VoERTP_RTCP::SetRTCP_CNAME() accepts a char[256] array.
std::string c_name_limited = c_name.substr(0, 255);
int error = channel()->SetRTCP_CNAME(c_name_limited.c_str());
int error = channel_->SetRTCP_CNAME(c_name_limited.c_str());
RTC_DCHECK_EQ(0, error);
}
void ChannelProxy::SetNACKStatus(bool enable, int max_packets) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->SetNACKStatus(enable, max_packets);
channel_->SetNACKStatus(enable, max_packets);
}
void ChannelProxy::SetSendAudioLevelIndicationStatus(bool enable, int id) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
int error = channel()->SetSendAudioLevelIndicationStatus(enable, id);
int error = channel_->SetSendAudioLevelIndicationStatus(enable, id);
RTC_DCHECK_EQ(0, error);
}
void ChannelProxy::SetReceiveAudioLevelIndicationStatus(bool enable, int id) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
int error = channel()->SetReceiveAudioLevelIndicationStatus(enable, id);
int error = channel_->SetReceiveAudioLevelIndicationStatus(enable, id);
RTC_DCHECK_EQ(0, error);
}
void ChannelProxy::EnableSendTransportSequenceNumber(int id) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->EnableSendTransportSequenceNumber(id);
channel_->EnableSendTransportSequenceNumber(id);
}
void ChannelProxy::EnableReceiveTransportSequenceNumber(int id) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->EnableReceiveTransportSequenceNumber(id);
channel_->EnableReceiveTransportSequenceNumber(id);
}
void ChannelProxy::RegisterSenderCongestionControlObjects(
RtpTransportControllerSendInterface* transport,
RtcpBandwidthObserver* bandwidth_observer) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->RegisterSenderCongestionControlObjects(transport,
channel_->RegisterSenderCongestionControlObjects(transport,
bandwidth_observer);
}
void ChannelProxy::RegisterReceiverCongestionControlObjects(
PacketRouter* packet_router) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->RegisterReceiverCongestionControlObjects(packet_router);
channel_->RegisterReceiverCongestionControlObjects(packet_router);
}
void ChannelProxy::ResetSenderCongestionControlObjects() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->ResetSenderCongestionControlObjects();
channel_->ResetSenderCongestionControlObjects();
}
void ChannelProxy::ResetReceiverCongestionControlObjects() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->ResetReceiverCongestionControlObjects();
channel_->ResetReceiverCongestionControlObjects();
}
CallStatistics ChannelProxy::GetRTCPStatistics() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
CallStatistics stats = {0};
int error = channel()->GetRTPStatistics(stats);
int error = channel_->GetRTPStatistics(stats);
RTC_DCHECK_EQ(0, error);
return stats;
}
@ -124,7 +123,7 @@ CallStatistics ChannelProxy::GetRTCPStatistics() const {
std::vector<ReportBlock> ChannelProxy::GetRemoteRTCPReportBlocks() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
std::vector<webrtc::ReportBlock> blocks;
int error = channel()->GetRemoteRTCPReportBlocks(&blocks);
int error = channel_->GetRemoteRTCPReportBlocks(&blocks);
RTC_DCHECK_EQ(0, error);
return blocks;
}
@ -132,7 +131,7 @@ std::vector<ReportBlock> ChannelProxy::GetRemoteRTCPReportBlocks() const {
NetworkStatistics ChannelProxy::GetNetworkStatistics() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
NetworkStatistics stats = {0};
int error = channel()->GetNetworkStatistics(stats);
int error = channel_->GetNetworkStatistics(stats);
RTC_DCHECK_EQ(0, error);
return stats;
}
@ -140,51 +139,51 @@ NetworkStatistics ChannelProxy::GetNetworkStatistics() const {
AudioDecodingCallStats ChannelProxy::GetDecodingCallStatistics() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
AudioDecodingCallStats stats;
channel()->GetDecodingCallStatistics(&stats);
channel_->GetDecodingCallStatistics(&stats);
return stats;
}
ANAStats ChannelProxy::GetANAStatistics() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return channel()->GetANAStatistics();
return channel_->GetANAStatistics();
}
int ChannelProxy::GetSpeechOutputLevel() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return channel()->GetSpeechOutputLevel();
return channel_->GetSpeechOutputLevel();
}
int ChannelProxy::GetSpeechOutputLevelFullRange() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return channel()->GetSpeechOutputLevelFullRange();
return channel_->GetSpeechOutputLevelFullRange();
}
double ChannelProxy::GetTotalOutputEnergy() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return channel()->GetTotalOutputEnergy();
return channel_->GetTotalOutputEnergy();
}
double ChannelProxy::GetTotalOutputDuration() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return channel()->GetTotalOutputDuration();
return channel_->GetTotalOutputDuration();
}
uint32_t ChannelProxy::GetDelayEstimate() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread() ||
module_process_thread_checker_.CalledOnValidThread());
return channel()->GetDelayEstimate();
return channel_->GetDelayEstimate();
}
bool ChannelProxy::SetSendTelephoneEventPayloadType(int payload_type,
int payload_frequency) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return channel()->SetSendTelephoneEventPayloadType(payload_type,
return channel_->SetSendTelephoneEventPayloadType(payload_type,
payload_frequency) == 0;
}
bool ChannelProxy::SendTelephoneEventOutband(int event, int duration_ms) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return channel()->SendTelephoneEventOutband(event, duration_ms) == 0;
return channel_->SendTelephoneEventOutband(event, duration_ms) == 0;
}
void ChannelProxy::SetBitrate(int bitrate_bps, int64_t probing_interval_ms) {
@ -194,88 +193,82 @@ void ChannelProxy::SetBitrate(int bitrate_bps, int64_t probing_interval_ms) {
// rules.
// RTC_DCHECK(worker_thread_checker_.CalledOnValidThread() ||
// module_process_thread_checker_.CalledOnValidThread());
channel()->SetBitRate(bitrate_bps, probing_interval_ms);
channel_->SetBitRate(bitrate_bps, probing_interval_ms);
}
void ChannelProxy::SetReceiveCodecs(
const std::map<int, SdpAudioFormat>& codecs) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->SetReceiveCodecs(codecs);
channel_->SetReceiveCodecs(codecs);
}
void ChannelProxy::SetSink(std::unique_ptr<AudioSinkInterface> sink) {
void ChannelProxy::SetSink(AudioSinkInterface* sink) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->SetSink(std::move(sink));
channel_->SetSink(sink);
}
void ChannelProxy::SetInputMute(bool muted) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->SetInputMute(muted);
channel_->SetInputMute(muted);
}
void ChannelProxy::RegisterTransport(Transport* transport) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->RegisterTransport(transport);
channel_->RegisterTransport(transport);
}
void ChannelProxy::OnRtpPacket(const RtpPacketReceived& packet) {
// May be called on either worker thread or network thread.
channel()->OnRtpPacket(packet);
channel_->OnRtpPacket(packet);
}
bool ChannelProxy::ReceivedRTCPPacket(const uint8_t* packet, size_t length) {
// May be called on either worker thread or network thread.
return channel()->ReceivedRTCPPacket(packet, length) == 0;
}
const rtc::scoped_refptr<AudioDecoderFactory>&
ChannelProxy::GetAudioDecoderFactory() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return channel()->GetAudioDecoderFactory();
return channel_->ReceivedRTCPPacket(packet, length) == 0;
}
void ChannelProxy::SetChannelOutputVolumeScaling(float scaling) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->SetChannelOutputVolumeScaling(scaling);
channel_->SetChannelOutputVolumeScaling(scaling);
}
void ChannelProxy::SetRtcEventLog(RtcEventLog* event_log) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->SetRtcEventLog(event_log);
channel_->SetRtcEventLog(event_log);
}
AudioMixer::Source::AudioFrameInfo ChannelProxy::GetAudioFrameWithInfo(
int sample_rate_hz,
AudioFrame* audio_frame) {
RTC_DCHECK_RUNS_SERIALIZED(&audio_thread_race_checker_);
return channel()->GetAudioFrameWithInfo(sample_rate_hz, audio_frame);
return channel_->GetAudioFrameWithInfo(sample_rate_hz, audio_frame);
}
int ChannelProxy::PreferredSampleRate() const {
RTC_DCHECK_RUNS_SERIALIZED(&audio_thread_race_checker_);
return channel()->PreferredSampleRate();
return channel_->PreferredSampleRate();
}
void ChannelProxy::ProcessAndEncodeAudio(
std::unique_ptr<AudioFrame> audio_frame) {
RTC_DCHECK_RUNS_SERIALIZED(&audio_thread_race_checker_);
return channel()->ProcessAndEncodeAudio(std::move(audio_frame));
return channel_->ProcessAndEncodeAudio(std::move(audio_frame));
}
void ChannelProxy::SetTransportOverhead(int transport_overhead_per_packet) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->SetTransportOverhead(transport_overhead_per_packet);
channel_->SetTransportOverhead(transport_overhead_per_packet);
}
void ChannelProxy::AssociateSendChannel(
const ChannelProxy& send_channel_proxy) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->set_associate_send_channel(send_channel_proxy.channel_owner_);
channel_->SetAssociatedSendChannel(send_channel_proxy.channel_.get());
}
void ChannelProxy::DisassociateSendChannel() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->set_associate_send_channel(ChannelOwner(nullptr));
channel_->SetAssociatedSendChannel(nullptr);
}
void ChannelProxy::GetRtpRtcp(RtpRtcp** rtp_rtcp,
@ -283,14 +276,14 @@ void ChannelProxy::GetRtpRtcp(RtpRtcp** rtp_rtcp,
RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread());
RTC_DCHECK(rtp_rtcp);
RTC_DCHECK(rtp_receiver);
int error = channel()->GetRtpRtcp(rtp_rtcp, rtp_receiver);
int error = channel_->GetRtpRtcp(rtp_rtcp, rtp_receiver);
RTC_DCHECK_EQ(0, error);
}
uint32_t ChannelProxy::GetPlayoutTimestamp() const {
RTC_DCHECK_RUNS_SERIALIZED(&video_capture_thread_race_checker_);
unsigned int timestamp = 0;
int error = channel()->GetPlayoutTimestamp(timestamp);
int error = channel_->GetPlayoutTimestamp(timestamp);
RTC_DCHECK(!error || timestamp == 0);
return timestamp;
}
@ -300,7 +293,7 @@ void ChannelProxy::SetMinimumPlayoutDelay(int delay_ms) {
// Limit to range accepted by both VoE and ACM, so we're at least getting as
// close as possible, instead of failing.
delay_ms = rtc::SafeClamp(delay_ms, 0, 10000);
int error = channel()->SetMinimumPlayoutDelay(delay_ms);
int error = channel_->SetMinimumPlayoutDelay(delay_ms);
if (0 != error) {
RTC_LOG(LS_WARNING) << "Error setting minimum playout delay.";
}
@ -308,57 +301,51 @@ void ChannelProxy::SetMinimumPlayoutDelay(int delay_ms) {
void ChannelProxy::SetRtcpRttStats(RtcpRttStats* rtcp_rtt_stats) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->SetRtcpRttStats(rtcp_rtt_stats);
channel_->SetRtcpRttStats(rtcp_rtt_stats);
}
bool ChannelProxy::GetRecCodec(CodecInst* codec_inst) const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return channel()->GetRecCodec(*codec_inst) == 0;
return channel_->GetRecCodec(*codec_inst) == 0;
}
void ChannelProxy::OnTwccBasedUplinkPacketLossRate(float packet_loss_rate) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->OnTwccBasedUplinkPacketLossRate(packet_loss_rate);
channel_->OnTwccBasedUplinkPacketLossRate(packet_loss_rate);
}
void ChannelProxy::OnRecoverableUplinkPacketLossRate(
float recoverable_packet_loss_rate) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->OnRecoverableUplinkPacketLossRate(recoverable_packet_loss_rate);
channel_->OnRecoverableUplinkPacketLossRate(recoverable_packet_loss_rate);
}
std::vector<RtpSource> ChannelProxy::GetSources() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return channel()->GetSources();
return channel_->GetSources();
}
void ChannelProxy::StartSend() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
int error = channel()->StartSend();
int error = channel_->StartSend();
RTC_DCHECK_EQ(0, error);
}
void ChannelProxy::StopSend() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->StopSend();
channel_->StopSend();
}
void ChannelProxy::StartPlayout() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
int error = channel()->StartPlayout();
int error = channel_->StartPlayout();
RTC_DCHECK_EQ(0, error);
}
void ChannelProxy::StopPlayout() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
int error = channel()->StopPlayout();
int error = channel_->StopPlayout();
RTC_DCHECK_EQ(0, error);
}
Channel* ChannelProxy::channel() const {
RTC_DCHECK(channel_owner_.channel());
return channel_owner_.channel();
}
} // namespace voe
} // namespace webrtc

View File

@ -11,6 +11,10 @@
#ifndef VOICE_ENGINE_CHANNEL_PROXY_H_
#define VOICE_ENGINE_CHANNEL_PROXY_H_
#include <memory>
#include <string>
#include <vector>
#include "api/audio/audio_mixer.h"
#include "api/audio_codecs/audio_encoder.h"
#include "api/rtpreceiverinterface.h"
@ -19,11 +23,6 @@
#include "rtc_base/race_checker.h"
#include "rtc_base/thread_checker.h"
#include "voice_engine/channel.h"
#include "voice_engine/channel_manager.h"
#include <memory>
#include <string>
#include <vector>
namespace webrtc {
@ -52,7 +51,7 @@ namespace voe {
class ChannelProxy : public RtpPacketSinkInterface {
public:
ChannelProxy();
explicit ChannelProxy(const ChannelOwner& channel_owner);
explicit ChannelProxy(std::unique_ptr<Channel> channel);
virtual ~ChannelProxy();
virtual bool SetEncoder(int payload_type,
@ -92,15 +91,13 @@ class ChannelProxy : public RtpPacketSinkInterface {
virtual bool SendTelephoneEventOutband(int event, int duration_ms);
virtual void SetBitrate(int bitrate_bps, int64_t probing_interval_ms);
virtual void SetReceiveCodecs(const std::map<int, SdpAudioFormat>& codecs);
virtual void SetSink(std::unique_ptr<AudioSinkInterface> sink);
virtual void SetSink(AudioSinkInterface* sink);
virtual void SetInputMute(bool muted);
virtual void RegisterTransport(Transport* transport);
// Implements RtpPacketSinkInterface
void OnRtpPacket(const RtpPacketReceived& packet) override;
virtual bool ReceivedRTCPPacket(const uint8_t* packet, size_t length);
virtual const rtc::scoped_refptr<AudioDecoderFactory>&
GetAudioDecoderFactory() const;
virtual void SetChannelOutputVolumeScaling(float scaling);
virtual void SetRtcEventLog(RtcEventLog* event_log);
virtual AudioMixer::Source::AudioFrameInfo GetAudioFrameWithInfo(
@ -127,8 +124,6 @@ class ChannelProxy : public RtpPacketSinkInterface {
virtual void StopPlayout();
private:
Channel* channel() const;
// Thread checkers document and lock usage of some methods on voe::Channel to
// specific threads we know about. The goal is to eventually split up
// voe::Channel into parts with single-threaded semantics, and thereby reduce
@ -141,7 +136,7 @@ class ChannelProxy : public RtpPacketSinkInterface {
// audio thread to another, but access is still sequential.
rtc::RaceChecker audio_thread_race_checker_;
rtc::RaceChecker video_capture_thread_race_checker_;
ChannelOwner channel_owner_;
std::unique_ptr<Channel> channel_;
RTC_DISALLOW_COPY_AND_ASSIGN(ChannelProxy);
};

View File

@ -1,15 +0,0 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "test/gtest.h"
#include "voice_engine/channel.h"
// Empty test just to get coverage metrics.
TEST(ChannelTest, EmptyTestToGetCodeCoverage) {}

View File

@ -102,7 +102,6 @@ class WEBRTC_DLLEXPORT VoEBase {
// decoder_factory member of the ACM config will be ignored (the decoder
// factory set through Init() will always be used).
// Returns channel ID or -1 in case of an error.
virtual int CreateChannel() = 0;
virtual int CreateChannel(const ChannelConfig& config) = 0;
// Deletes an existing channel and releases the utilized resources.

View File

@ -1,48 +0,0 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "voice_engine/shared_data.h"
#include "voice_engine/channel.h"
namespace webrtc {
namespace voe {
static int32_t _gInstanceCounter = 0;
SharedData::SharedData()
: _instanceId(++_gInstanceCounter),
_channelManager(_gInstanceCounter),
_audioDevicePtr(NULL),
_moduleProcessThreadPtr(ProcessThread::Create("VoiceProcessThread")),
encoder_queue_("AudioEncoderQueue") {
}
SharedData::~SharedData()
{
if (_audioDevicePtr) {
_audioDevicePtr->Release();
}
_moduleProcessThreadPtr->Stop();
}
rtc::TaskQueue* SharedData::encoder_queue() {
RTC_DCHECK_RUN_ON(&construction_thread_);
return &encoder_queue_;
}
void SharedData::set_audio_device(
const rtc::scoped_refptr<AudioDeviceModule>& audio_device) {
_audioDevicePtr = audio_device;
}
} // namespace voe
} // namespace webrtc

View File

@ -1,60 +0,0 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VOICE_ENGINE_SHARED_DATA_H_
#define VOICE_ENGINE_SHARED_DATA_H_
#include <memory>
#include "modules/audio_device/include/audio_device.h"
#include "modules/utility/include/process_thread.h"
#include "rtc_base/criticalsection.h"
#include "rtc_base/scoped_ref_ptr.h"
#include "rtc_base/task_queue.h"
#include "rtc_base/thread_annotations.h"
#include "rtc_base/thread_checker.h"
#include "voice_engine/channel_manager.h"
class ProcessThread;
namespace webrtc {
namespace voe {
class SharedData
{
public:
// Public accessors.
uint32_t instance_id() const { return _instanceId; }
ChannelManager& channel_manager() { return _channelManager; }
AudioDeviceModule* audio_device() { return _audioDevicePtr.get(); }
void set_audio_device(
const rtc::scoped_refptr<AudioDeviceModule>& audio_device);
rtc::CriticalSection* crit_sec() { return &_apiCritPtr; }
ProcessThread* process_thread() { return _moduleProcessThreadPtr.get(); }
rtc::TaskQueue* encoder_queue();
protected:
rtc::ThreadChecker construction_thread_;
const uint32_t _instanceId;
rtc::CriticalSection _apiCritPtr;
ChannelManager _channelManager;
rtc::scoped_refptr<AudioDeviceModule> _audioDevicePtr;
std::unique_ptr<ProcessThread> _moduleProcessThreadPtr;
// |encoder_queue| is defined last to ensure all pending tasks are cancelled
// and deleted before any other members.
rtc::TaskQueue encoder_queue_ RTC_ACCESS_ON(construction_thread_);
SharedData();
virtual ~SharedData();
};
} // namespace voe
} // namespace webrtc
#endif // VOICE_ENGINE_SHARED_DATA_H_

View File

@ -10,14 +10,6 @@
#include "voice_engine/voe_base_impl.h"
#include "common_audio/signal_processing/include/signal_processing_library.h"
#include "modules/audio_coding/include/audio_coding_module.h"
#include "modules/audio_device/audio_device_impl.h"
#include "rtc_base/format_macros.h"
#include "rtc_base/location.h"
#include "rtc_base/logging.h"
#include "voice_engine/channel.h"
#include "voice_engine/include/voe_errors.h"
#include "voice_engine/voice_engine_impl.h"
namespace webrtc {
@ -31,93 +23,7 @@ VoEBase* VoEBase::GetInterface(VoiceEngine* voiceEngine) {
return s;
}
VoEBaseImpl::VoEBaseImpl(voe::SharedData* shared)
: shared_(shared) {}
VoEBaseImpl::VoEBaseImpl() {}
VoEBaseImpl::~VoEBaseImpl() {
TerminateInternal();
}
int VoEBaseImpl::Init(
AudioDeviceModule* audio_device,
AudioProcessing* audio_processing,
const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory) {
RTC_DCHECK(audio_device);
rtc::CritScope cs(shared_->crit_sec());
if (shared_->process_thread()) {
shared_->process_thread()->Start();
}
shared_->set_audio_device(audio_device);
RTC_DCHECK(decoder_factory);
decoder_factory_ = decoder_factory;
return 0;
}
void VoEBaseImpl::Terminate() {
rtc::CritScope cs(shared_->crit_sec());
TerminateInternal();
}
int VoEBaseImpl::CreateChannel() {
return CreateChannel(ChannelConfig());
}
int VoEBaseImpl::CreateChannel(const ChannelConfig& config) {
rtc::CritScope cs(shared_->crit_sec());
ChannelConfig config_copy(config);
config_copy.acm_config.decoder_factory = decoder_factory_;
voe::ChannelOwner channel_owner =
shared_->channel_manager().CreateChannel(config_copy);
return InitializeChannel(&channel_owner);
}
int VoEBaseImpl::InitializeChannel(voe::ChannelOwner* channel_owner) {
if (channel_owner->channel()->SetEngineInformation(
*shared_->process_thread(), *shared_->audio_device(),
shared_->encoder_queue()) != 0) {
RTC_LOG(LS_ERROR)
<< "CreateChannel() failed to associate engine and channel."
" Destroying channel.";
shared_->channel_manager().DestroyChannel(
channel_owner->channel()->ChannelId());
return -1;
} else if (channel_owner->channel()->Init() != 0) {
RTC_LOG(LS_ERROR)
<< "CreateChannel() failed to initialize channel. Destroying"
" channel.";
shared_->channel_manager().DestroyChannel(
channel_owner->channel()->ChannelId());
return -1;
}
return channel_owner->channel()->ChannelId();
}
int VoEBaseImpl::DeleteChannel(int channel) {
rtc::CritScope cs(shared_->crit_sec());
{
voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == nullptr) {
RTC_LOG(LS_ERROR) << "DeleteChannel() failed to locate channel";
return -1;
}
}
shared_->channel_manager().DestroyChannel(channel);
return 0;
}
void VoEBaseImpl::TerminateInternal() {
// Delete any remaining channel objects
shared_->channel_manager().DestroyAllChannels();
if (shared_->process_thread()) {
shared_->process_thread()->Stop();
}
shared_->set_audio_device(nullptr);
}
VoEBaseImpl::~VoEBaseImpl() {}
} // namespace webrtc

View File

@ -13,38 +13,24 @@
#include "voice_engine/include/voe_base.h"
#include "modules/include/module_common_types.h"
#include "rtc_base/criticalsection.h"
#include "voice_engine/shared_data.h"
namespace webrtc {
class ProcessThread;
class VoEBaseImpl : public VoEBase {
public:
int Init(
AudioDeviceModule* audio_device,
AudioProcessing* audio_processing,
const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory) override;
void Terminate() override;
const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory) override {
return 0;
}
void Terminate() override {}
int CreateChannel() override;
int CreateChannel(const ChannelConfig& config) override;
int DeleteChannel(int channel) override;
int CreateChannel(const ChannelConfig& config) override { return 1; }
int DeleteChannel(int channel) override { return 0; }
protected:
VoEBaseImpl(voe::SharedData* shared);
VoEBaseImpl();
~VoEBaseImpl() override;
private:
void TerminateInternal();
// Initialize channel by setting Engine Information then initializing
// channel.
int InitializeChannel(voe::ChannelOwner* channel_owner);
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory_;
voe::SharedData* shared_;
};
} // namespace webrtc

View File

@ -1,51 +0,0 @@
/*
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "voice_engine/include/voe_base.h"
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "modules/audio_device/include/fake_audio_device.h"
#include "test/gtest.h"
namespace webrtc {
class VoEBaseTest : public ::testing::Test {
protected:
VoEBaseTest()
: voe_(VoiceEngine::Create()),
base_(VoEBase::GetInterface(voe_)) {
EXPECT_NE(nullptr, base_);
}
~VoEBaseTest() {
base_->Terminate();
EXPECT_EQ(1, base_->Release());
EXPECT_TRUE(VoiceEngine::Delete(voe_));
}
VoiceEngine* voe_;
VoEBase* base_;
FakeAudioDeviceModule adm_;
};
TEST_F(VoEBaseTest, InitWithExternalAudioDevice) {
EXPECT_EQ(0,
base_->Init(&adm_, nullptr, CreateBuiltinAudioDecoderFactory()));
}
TEST_F(VoEBaseTest, CreateChannelAfterInit) {
EXPECT_EQ(0,
base_->Init(&adm_, nullptr, CreateBuiltinAudioDecoderFactory()));
int channelID = base_->CreateChannel();
EXPECT_NE(channelID, -1);
EXPECT_EQ(0, base_->DeleteChannel(channelID));
}
} // namespace webrtc

View File

@ -7,16 +7,6 @@
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#if defined(WEBRTC_ANDROID)
#include "modules/audio_device/android/audio_device_template.h"
#include "modules/audio_device/android/audio_record_jni.h"
#include "modules/audio_device/android/audio_track_jni.h"
#endif
#include "modules/audio_coding/include/audio_coding_module.h"
#include "rtc_base/checks.h"
#include "voice_engine/channel_proxy.h"
#include "voice_engine/voice_engine_impl.h"
namespace webrtc {
@ -57,14 +47,6 @@ int VoiceEngineImpl::Release() {
return new_ref;
}
std::unique_ptr<voe::ChannelProxy> VoiceEngineImpl::GetChannelProxy(
int channel_id) {
RTC_DCHECK(channel_id >= 0);
rtc::CritScope cs(crit_sec());
return std::unique_ptr<voe::ChannelProxy>(
new voe::ChannelProxy(channel_manager().GetChannel(channel_id)));
}
VoiceEngine* VoiceEngine::Create() {
return GetVoiceEngine();
}

View File

@ -18,17 +18,12 @@
#include "voice_engine/voe_base_impl.h"
namespace webrtc {
namespace voe {
class ChannelProxy;
} // namespace voe
class VoiceEngineImpl : public voe::SharedData, // Must be the first base class
public VoiceEngine,
class VoiceEngineImpl : public VoiceEngine,
public VoEBaseImpl {
public:
VoiceEngineImpl()
: SharedData(),
VoEBaseImpl(this),
: VoEBaseImpl(),
_ref_count(0) {}
~VoiceEngineImpl() override { assert(_ref_count.Value() == 0); }
@ -37,10 +32,6 @@ class VoiceEngineImpl : public voe::SharedData, // Must be the first base class
// This implements the Release() method for all the inherited interfaces.
int Release() override;
// Backdoor to access a voe::Channel object without a channel ID. This is only
// to be used while refactoring the VoE API!
virtual std::unique_ptr<voe::ChannelProxy> GetChannelProxy(int channel_id);
// This is *protected* so that FakeVoiceEngine can inherit from the class and
// manipulate the reference count. See: fake_voice_engine.h.
protected: