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:
parent
aa6b24f23c
commit
8f5787a919
@ -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",
|
||||
]
|
||||
|
||||
@ -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 ||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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());
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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_
|
||||
@ -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",
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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: "
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
11
call/call.cc
11
call/call.cc
@ -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] =
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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" ]
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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_
|
||||
@ -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;
|
||||
|
||||
@ -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_
|
||||
@ -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());
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 =
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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_;
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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_
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 = [
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
|
||||
@ -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
|
||||
@ -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_
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
@ -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) {}
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
@ -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_
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user