aboutsummaryrefslogtreecommitdiff
path: root/talk/media/webrtc
diff options
context:
space:
mode:
Diffstat (limited to 'talk/media/webrtc')
-rw-r--r--talk/media/webrtc/fakewebrtccall.cc26
-rw-r--r--talk/media/webrtc/fakewebrtccall.h28
-rw-r--r--talk/media/webrtc/fakewebrtcvideoengine.h2
-rw-r--r--talk/media/webrtc/fakewebrtcvoiceengine.h269
-rwxr-xr-xtalk/media/webrtc/simulcast.cc6
-rw-r--r--talk/media/webrtc/webrtcmediaengine.cc106
-rw-r--r--talk/media/webrtc/webrtcmediaengine.h19
-rw-r--r--talk/media/webrtc/webrtcmediaengine_unittest.cc205
-rw-r--r--talk/media/webrtc/webrtcvideocapturer.cc14
-rw-r--r--talk/media/webrtc/webrtcvideocapturer.h2
-rw-r--r--talk/media/webrtc/webrtcvideocapturer_unittest.cc1
-rw-r--r--talk/media/webrtc/webrtcvideoengine2.cc476
-rw-r--r--talk/media/webrtc/webrtcvideoengine2.h40
-rw-r--r--talk/media/webrtc/webrtcvideoengine2_unittest.cc258
-rw-r--r--talk/media/webrtc/webrtcvideoframe.cc19
-rw-r--r--talk/media/webrtc/webrtcvideoframe.h11
-rw-r--r--talk/media/webrtc/webrtcvoe.h24
-rw-r--r--talk/media/webrtc/webrtcvoiceengine.cc1823
-rw-r--r--talk/media/webrtc/webrtcvoiceengine.h145
-rw-r--r--talk/media/webrtc/webrtcvoiceengine_unittest.cc724
20 files changed, 1888 insertions, 2310 deletions
diff --git a/talk/media/webrtc/fakewebrtccall.cc b/talk/media/webrtc/fakewebrtccall.cc
index d86bfb553c..d50a53cb63 100644
--- a/talk/media/webrtc/fakewebrtccall.cc
+++ b/talk/media/webrtc/fakewebrtccall.cc
@@ -28,10 +28,12 @@
#include "talk/media/webrtc/fakewebrtccall.h"
#include <algorithm>
+#include <utility>
#include "talk/media/base/rtputils.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/gunit.h"
+#include "webrtc/audio/audio_sink.h"
namespace cricket {
FakeAudioSendStream::FakeAudioSendStream(
@@ -39,14 +41,27 @@ FakeAudioSendStream::FakeAudioSendStream(
RTC_DCHECK(config.voe_channel_id != -1);
}
+const webrtc::AudioSendStream::Config&
+ FakeAudioSendStream::GetConfig() const {
+ return config_;
+}
+
void FakeAudioSendStream::SetStats(
const webrtc::AudioSendStream::Stats& stats) {
stats_ = stats;
}
-const webrtc::AudioSendStream::Config&
- FakeAudioSendStream::GetConfig() const {
- return config_;
+FakeAudioSendStream::TelephoneEvent
+ FakeAudioSendStream::GetLatestTelephoneEvent() const {
+ return latest_telephone_event_;
+}
+
+bool FakeAudioSendStream::SendTelephoneEvent(int payload_type, uint8_t event,
+ uint32_t duration_ms) {
+ latest_telephone_event_.payload_type = payload_type;
+ latest_telephone_event_.event_code = event;
+ latest_telephone_event_.duration_ms = duration_ms;
+ return true;
}
webrtc::AudioSendStream::Stats FakeAudioSendStream::GetStats() const {
@@ -77,6 +92,11 @@ webrtc::AudioReceiveStream::Stats FakeAudioReceiveStream::GetStats() const {
return stats_;
}
+void FakeAudioReceiveStream::SetSink(
+ rtc::scoped_ptr<webrtc::AudioSinkInterface> sink) {
+ sink_ = std::move(sink);
+}
+
FakeVideoSendStream::FakeVideoSendStream(
const webrtc::VideoSendStream::Config& config,
const webrtc::VideoEncoderConfig& encoder_config)
diff --git a/talk/media/webrtc/fakewebrtccall.h b/talk/media/webrtc/fakewebrtccall.h
index 88edc60d78..3528c7a7b1 100644
--- a/talk/media/webrtc/fakewebrtccall.h
+++ b/talk/media/webrtc/fakewebrtccall.h
@@ -47,14 +47,19 @@
#include "webrtc/video_send_stream.h"
namespace cricket {
-
-class FakeAudioSendStream : public webrtc::AudioSendStream {
+class FakeAudioSendStream final : public webrtc::AudioSendStream {
public:
- explicit FakeAudioSendStream(
- const webrtc::AudioSendStream::Config& config);
+ struct TelephoneEvent {
+ int payload_type = -1;
+ uint8_t event_code = 0;
+ uint32_t duration_ms = 0;
+ };
+
+ explicit FakeAudioSendStream(const webrtc::AudioSendStream::Config& config);
const webrtc::AudioSendStream::Config& GetConfig() const;
void SetStats(const webrtc::AudioSendStream::Stats& stats);
+ TelephoneEvent GetLatestTelephoneEvent() const;
private:
// webrtc::SendStream implementation.
@@ -66,13 +71,16 @@ class FakeAudioSendStream : public webrtc::AudioSendStream {
}
// webrtc::AudioSendStream implementation.
+ bool SendTelephoneEvent(int payload_type, uint8_t event,
+ uint32_t duration_ms) override;
webrtc::AudioSendStream::Stats GetStats() const override;
+ TelephoneEvent latest_telephone_event_;
webrtc::AudioSendStream::Config config_;
webrtc::AudioSendStream::Stats stats_;
};
-class FakeAudioReceiveStream : public webrtc::AudioReceiveStream {
+class FakeAudioReceiveStream final : public webrtc::AudioReceiveStream {
public:
explicit FakeAudioReceiveStream(
const webrtc::AudioReceiveStream::Config& config);
@@ -98,14 +106,16 @@ class FakeAudioReceiveStream : public webrtc::AudioReceiveStream {
// webrtc::AudioReceiveStream implementation.
webrtc::AudioReceiveStream::Stats GetStats() const override;
+ void SetSink(rtc::scoped_ptr<webrtc::AudioSinkInterface> sink) override;
webrtc::AudioReceiveStream::Config config_;
webrtc::AudioReceiveStream::Stats stats_;
int received_packets_;
+ rtc::scoped_ptr<webrtc::AudioSinkInterface> sink_;
};
-class FakeVideoSendStream : public webrtc::VideoSendStream,
- public webrtc::VideoCaptureInput {
+class FakeVideoSendStream final : public webrtc::VideoSendStream,
+ public webrtc::VideoCaptureInput {
public:
FakeVideoSendStream(const webrtc::VideoSendStream::Config& config,
const webrtc::VideoEncoderConfig& encoder_config);
@@ -153,7 +163,7 @@ class FakeVideoSendStream : public webrtc::VideoSendStream,
webrtc::VideoSendStream::Stats stats_;
};
-class FakeVideoReceiveStream : public webrtc::VideoReceiveStream {
+class FakeVideoReceiveStream final : public webrtc::VideoReceiveStream {
public:
explicit FakeVideoReceiveStream(
const webrtc::VideoReceiveStream::Config& config);
@@ -188,7 +198,7 @@ class FakeVideoReceiveStream : public webrtc::VideoReceiveStream {
webrtc::VideoReceiveStream::Stats stats_;
};
-class FakeCall : public webrtc::Call, public webrtc::PacketReceiver {
+class FakeCall final : public webrtc::Call, public webrtc::PacketReceiver {
public:
explicit FakeCall(const webrtc::Call::Config& config);
~FakeCall() override;
diff --git a/talk/media/webrtc/fakewebrtcvideoengine.h b/talk/media/webrtc/fakewebrtcvideoengine.h
index 8e4c7c87f8..e0d4db52f8 100644
--- a/talk/media/webrtc/fakewebrtcvideoengine.h
+++ b/talk/media/webrtc/fakewebrtcvideoengine.h
@@ -41,7 +41,7 @@
#include "webrtc/base/gunit.h"
#include "webrtc/base/stringutils.h"
#include "webrtc/base/thread_annotations.h"
-#include "webrtc/modules/video_coding/codecs/interface/video_error_codes.h"
+#include "webrtc/modules/video_coding/include/video_error_codes.h"
#include "webrtc/video_decoder.h"
#include "webrtc/video_encoder.h"
diff --git a/talk/media/webrtc/fakewebrtcvoiceengine.h b/talk/media/webrtc/fakewebrtcvoiceengine.h
index 2405e07b5f..65ba927cc5 100644
--- a/talk/media/webrtc/fakewebrtcvoiceengine.h
+++ b/talk/media/webrtc/fakewebrtcvoiceengine.h
@@ -41,19 +41,11 @@
#include "webrtc/base/gunit.h"
#include "webrtc/base/stringutils.h"
#include "webrtc/config.h"
+#include "webrtc/modules/audio_coding/acm2/rent_a_codec.h"
#include "webrtc/modules/audio_processing/include/audio_processing.h"
namespace cricket {
-static const char kFakeDefaultDeviceName[] = "Fake Default";
-static const int kFakeDefaultDeviceId = -1;
-static const char kFakeDeviceName[] = "Fake Device";
-#ifdef WIN32
-static const int kFakeDeviceId = 0;
-#else
-static const int kFakeDeviceId = 1;
-#endif
-
static const int kOpusBandwidthNb = 4000;
static const int kOpusBandwidthMb = 6000;
static const int kOpusBandwidthWb = 8000;
@@ -63,18 +55,6 @@ static const int kOpusBandwidthFb = 20000;
#define WEBRTC_CHECK_CHANNEL(channel) \
if (channels_.find(channel) == channels_.end()) return -1;
-#define WEBRTC_ASSERT_CHANNEL(channel) \
- RTC_DCHECK(channels_.find(channel) != channels_.end());
-
-// Verify the header extension ID, if enabled, is within the bounds specified in
-// [RFC5285]: 1-14 inclusive.
-#define WEBRTC_CHECK_HEADER_EXTENSION_ID(enable, id) \
- do { \
- if (enable && (id < 1 || id > 14)) { \
- return -1; \
- } \
- } while (0);
-
class FakeAudioProcessing : public webrtc::AudioProcessing {
public:
FakeAudioProcessing() : experimental_ns_enabled_(false) {}
@@ -94,11 +74,13 @@ class FakeAudioProcessing : public webrtc::AudioProcessing {
experimental_ns_enabled_ = config.Get<webrtc::ExperimentalNs>().enabled;
}
+ WEBRTC_STUB_CONST(input_sample_rate_hz, ());
WEBRTC_STUB_CONST(proc_sample_rate_hz, ());
WEBRTC_STUB_CONST(proc_split_sample_rate_hz, ());
- WEBRTC_STUB_CONST(num_input_channels, ());
- WEBRTC_STUB_CONST(num_output_channels, ());
- WEBRTC_STUB_CONST(num_reverse_channels, ());
+ size_t num_input_channels() const override { return 0; }
+ size_t num_proc_channels() const override { return 0; }
+ size_t num_output_channels() const override { return 0; }
+ size_t num_reverse_channels() const override { return 0; }
WEBRTC_VOID_STUB(set_output_will_be_muted, (bool muted));
WEBRTC_STUB(ProcessStream, (webrtc::AudioFrame* frame));
WEBRTC_STUB(ProcessStream, (
@@ -156,20 +138,11 @@ class FakeAudioProcessing : public webrtc::AudioProcessing {
class FakeWebRtcVoiceEngine
: public webrtc::VoEAudioProcessing,
- public webrtc::VoEBase, public webrtc::VoECodec, public webrtc::VoEDtmf,
+ public webrtc::VoEBase, public webrtc::VoECodec,
public webrtc::VoEHardware,
public webrtc::VoENetwork, public webrtc::VoERTP_RTCP,
public webrtc::VoEVolumeControl {
public:
- struct DtmfInfo {
- DtmfInfo()
- : dtmf_event_code(-1),
- dtmf_out_of_band(false),
- dtmf_length_ms(-1) {}
- int dtmf_event_code;
- bool dtmf_out_of_band;
- int dtmf_length_ms;
- };
struct Channel {
explicit Channel()
: external_transport(false),
@@ -184,15 +157,11 @@ class FakeWebRtcVoiceEngine
nack(false),
cn8_type(13),
cn16_type(105),
- dtmf_type(106),
red_type(117),
nack_max_packets(0),
send_ssrc(0),
- send_audio_level_ext_(-1),
- receive_audio_level_ext_(-1),
- send_absolute_sender_time_ext_(-1),
- receive_absolute_sender_time_ext_(-1),
associate_send_channel(-1),
+ recv_codecs(),
neteq_capacity(-1),
neteq_fast_accelerate(false) {
memset(&send_codec, 0, sizeof(send_codec));
@@ -209,16 +178,10 @@ class FakeWebRtcVoiceEngine
bool nack;
int cn8_type;
int cn16_type;
- int dtmf_type;
int red_type;
int nack_max_packets;
uint32_t send_ssrc;
- int send_audio_level_ext_;
- int receive_audio_level_ext_;
- int send_absolute_sender_time_ext_;
- int receive_absolute_sender_time_ext_;
int associate_send_channel;
- DtmfInfo dtmf_info;
std::vector<webrtc::CodecInst> recv_codecs;
webrtc::CodecInst send_codec;
webrtc::PacketTime last_rtp_packet_time;
@@ -227,13 +190,10 @@ class FakeWebRtcVoiceEngine
bool neteq_fast_accelerate;
};
- FakeWebRtcVoiceEngine(const cricket::AudioCodec* const* codecs,
- int num_codecs)
+ FakeWebRtcVoiceEngine()
: inited_(false),
last_channel_(-1),
fail_create_channel_(false),
- codecs_(codecs),
- num_codecs_(num_codecs),
num_set_send_codecs_(0),
ec_enabled_(false),
ec_metrics_enabled_(false),
@@ -255,26 +215,13 @@ class FakeWebRtcVoiceEngine
memset(&agc_config_, 0, sizeof(agc_config_));
}
~FakeWebRtcVoiceEngine() {
- // Ought to have all been deleted by the WebRtcVoiceMediaChannel
- // destructors, but just in case ...
- for (std::map<int, Channel*>::const_iterator i = channels_.begin();
- i != channels_.end(); ++i) {
- delete i->second;
- }
+ RTC_CHECK(channels_.empty());
}
bool ec_metrics_enabled() const { return ec_metrics_enabled_; }
bool IsInited() const { return inited_; }
int GetLastChannel() const { return last_channel_; }
- int GetChannelFromLocalSsrc(uint32_t local_ssrc) const {
- for (std::map<int, Channel*>::const_iterator iter = channels_.begin();
- iter != channels_.end(); ++iter) {
- if (local_ssrc == iter->second->send_ssrc)
- return iter->first;
- }
- return -1;
- }
int GetNumChannels() const { return static_cast<int>(channels_.size()); }
uint32_t GetLocalSSRC(int channel) {
return channels_[channel]->send_ssrc;
@@ -307,7 +254,7 @@ class FakeWebRtcVoiceEngine
return channels_[channel]->nack_max_packets;
}
const webrtc::PacketTime& GetLastRtpPacketTime(int channel) {
- WEBRTC_ASSERT_CHANNEL(channel);
+ RTC_DCHECK(channels_.find(channel) != channels_.end());
return channels_[channel]->last_rtp_packet_time;
}
int GetSendCNPayloadType(int channel, bool wideband) {
@@ -315,9 +262,6 @@ class FakeWebRtcVoiceEngine
channels_[channel]->cn16_type :
channels_[channel]->cn8_type;
}
- int GetSendTelephoneEventPayloadType(int channel) {
- return channels_[channel]->dtmf_type;
- }
int GetSendREDPayloadType(int channel) {
return channels_[channel]->red_type;
}
@@ -351,11 +295,8 @@ class FakeWebRtcVoiceEngine
return -1;
}
Channel* ch = new Channel();
- for (int i = 0; i < NumOfCodecs(); ++i) {
- webrtc::CodecInst codec;
- GetCodec(i, codec);
- ch->recv_codecs.push_back(codec);
- }
+ auto db = webrtc::acm2::RentACodec::Database();
+ ch->recv_codecs.assign(db.begin(), db.end());
if (config.Get<webrtc::NetEqCapacityConfig>().enabled) {
ch->neteq_capacity = config.Get<webrtc::NetEqCapacityConfig>().capacity;
}
@@ -364,24 +305,6 @@ class FakeWebRtcVoiceEngine
channels_[++last_channel_] = ch;
return last_channel_;
}
- int GetSendRtpExtensionId(int channel, const std::string& extension) {
- WEBRTC_ASSERT_CHANNEL(channel);
- if (extension == kRtpAudioLevelHeaderExtension) {
- return channels_[channel]->send_audio_level_ext_;
- } else if (extension == kRtpAbsoluteSenderTimeHeaderExtension) {
- return channels_[channel]->send_absolute_sender_time_ext_;
- }
- return -1;
- }
- int GetReceiveRtpExtensionId(int channel, const std::string& extension) {
- WEBRTC_ASSERT_CHANNEL(channel);
- if (extension == kRtpAudioLevelHeaderExtension) {
- return channels_[channel]->receive_audio_level_ext_;
- } else if (extension == kRtpAbsoluteSenderTimeHeaderExtension) {
- return channels_[channel]->receive_absolute_sender_time_ext_;
- }
- return -1;
- }
int GetNumSetSendCodecs() const { return num_set_send_codecs_; }
@@ -473,22 +396,8 @@ class FakeWebRtcVoiceEngine
webrtc::RtcEventLog* GetEventLog() { return nullptr; }
// webrtc::VoECodec
- WEBRTC_FUNC(NumOfCodecs, ()) {
- return num_codecs_;
- }
- WEBRTC_FUNC(GetCodec, (int index, webrtc::CodecInst& codec)) {
- if (index < 0 || index >= NumOfCodecs()) {
- return -1;
- }
- const cricket::AudioCodec& c(*codecs_[index]);
- codec.pltype = c.id;
- rtc::strcpyn(codec.plname, sizeof(codec.plname), c.name.c_str());
- codec.plfreq = c.clockrate;
- codec.pacsize = 0;
- codec.channels = c.channels;
- codec.rate = c.bitrate;
- return 0;
- }
+ WEBRTC_STUB(NumOfCodecs, ());
+ WEBRTC_STUB(GetCodec, (int index, webrtc::CodecInst& codec));
WEBRTC_FUNC(SetSendCodec, (int channel, const webrtc::CodecInst& codec)) {
WEBRTC_CHECK_CHANNEL(channel);
// To match the behavior of the real implementation.
@@ -526,16 +435,17 @@ class FakeWebRtcVoiceEngine
}
}
// Otherwise try to find this codec and update its payload type.
+ int result = -1; // not found
for (std::vector<webrtc::CodecInst>::iterator it = ch->recv_codecs.begin();
it != ch->recv_codecs.end(); ++it) {
if (strcmp(it->plname, codec.plname) == 0 &&
- it->plfreq == codec.plfreq) {
+ it->plfreq == codec.plfreq &&
+ it->channels == codec.channels) {
it->pltype = codec.pltype;
- it->channels = codec.channels;
- return 0;
+ result = 0;
}
}
- return -1; // not found
+ return result;
}
WEBRTC_FUNC(SetSendCNPayloadType, (int channel, int type,
webrtc::PayloadFrequencies frequency)) {
@@ -620,46 +530,11 @@ class FakeWebRtcVoiceEngine
return 0;
}
- // webrtc::VoEDtmf
- WEBRTC_FUNC(SendTelephoneEvent, (int channel, int event_code,
- bool out_of_band = true, int length_ms = 160, int attenuation_db = 10)) {
- channels_[channel]->dtmf_info.dtmf_event_code = event_code;
- channels_[channel]->dtmf_info.dtmf_out_of_band = out_of_band;
- channels_[channel]->dtmf_info.dtmf_length_ms = length_ms;
- return 0;
- }
-
- WEBRTC_FUNC(SetSendTelephoneEventPayloadType,
- (int channel, unsigned char type)) {
- channels_[channel]->dtmf_type = type;
- return 0;
- };
- WEBRTC_STUB(GetSendTelephoneEventPayloadType,
- (int channel, unsigned char& type));
-
- WEBRTC_STUB(SetDtmfFeedbackStatus, (bool enable, bool directFeedback));
- WEBRTC_STUB(GetDtmfFeedbackStatus, (bool& enabled, bool& directFeedback));
-
- WEBRTC_FUNC(PlayDtmfTone,
- (int event_code, int length_ms = 200, int attenuation_db = 10)) {
- dtmf_info_.dtmf_event_code = event_code;
- dtmf_info_.dtmf_length_ms = length_ms;
- return 0;
- }
-
// webrtc::VoEHardware
- WEBRTC_FUNC(GetNumOfRecordingDevices, (int& num)) {
- return GetNumDevices(num);
- }
- WEBRTC_FUNC(GetNumOfPlayoutDevices, (int& num)) {
- return GetNumDevices(num);
- }
- WEBRTC_FUNC(GetRecordingDeviceName, (int i, char* name, char* guid)) {
- return GetDeviceName(i, name, guid);
- }
- WEBRTC_FUNC(GetPlayoutDeviceName, (int i, char* name, char* guid)) {
- return GetDeviceName(i, name, guid);
- }
+ WEBRTC_STUB(GetNumOfRecordingDevices, (int& num));
+ WEBRTC_STUB(GetNumOfPlayoutDevices, (int& num));
+ WEBRTC_STUB(GetRecordingDeviceName, (int i, char* name, char* guid));
+ WEBRTC_STUB(GetPlayoutDeviceName, (int i, char* name, char* guid));
WEBRTC_STUB(SetRecordingDevice, (int, webrtc::StereoChannel));
WEBRTC_STUB(SetPlayoutDevice, (int));
WEBRTC_STUB(SetAudioDeviceLayer, (webrtc::AudioLayers));
@@ -729,35 +604,14 @@ class FakeWebRtcVoiceEngine
}
WEBRTC_STUB(GetLocalSSRC, (int channel, unsigned int& ssrc));
WEBRTC_STUB(GetRemoteSSRC, (int channel, unsigned int& ssrc));
- WEBRTC_FUNC(SetSendAudioLevelIndicationStatus, (int channel, bool enable,
- unsigned char id)) {
- WEBRTC_CHECK_CHANNEL(channel);
- WEBRTC_CHECK_HEADER_EXTENSION_ID(enable, id);
- channels_[channel]->send_audio_level_ext_ = (enable) ? id : -1;
- return 0;
- }
- WEBRTC_FUNC(SetReceiveAudioLevelIndicationStatus, (int channel, bool enable,
- unsigned char id)) {
- WEBRTC_CHECK_CHANNEL(channel);
- WEBRTC_CHECK_HEADER_EXTENSION_ID(enable, id);
- channels_[channel]->receive_audio_level_ext_ = (enable) ? id : -1;
- return 0;
- }
- WEBRTC_FUNC(SetSendAbsoluteSenderTimeStatus, (int channel, bool enable,
- unsigned char id)) {
- WEBRTC_CHECK_CHANNEL(channel);
- WEBRTC_CHECK_HEADER_EXTENSION_ID(enable, id);
- channels_[channel]->send_absolute_sender_time_ext_ = (enable) ? id : -1;
- return 0;
- }
- WEBRTC_FUNC(SetReceiveAbsoluteSenderTimeStatus, (int channel, bool enable,
- unsigned char id)) {
- WEBRTC_CHECK_CHANNEL(channel);
- WEBRTC_CHECK_HEADER_EXTENSION_ID(enable, id);
- channels_[channel]->receive_absolute_sender_time_ext_ = (enable) ? id : -1;
- return 0;
- }
-
+ WEBRTC_STUB(SetSendAudioLevelIndicationStatus, (int channel, bool enable,
+ unsigned char id));
+ WEBRTC_STUB(SetReceiveAudioLevelIndicationStatus, (int channel, bool enable,
+ unsigned char id));
+ WEBRTC_STUB(SetSendAbsoluteSenderTimeStatus, (int channel, bool enable,
+ unsigned char id));
+ WEBRTC_STUB(SetReceiveAbsoluteSenderTimeStatus, (int channel, bool enable,
+ unsigned char id));
WEBRTC_STUB(SetRTCPStatus, (int channel, bool enable));
WEBRTC_STUB(GetRTCPStatus, (int channel, bool& enabled));
WEBRTC_STUB(SetRTCP_CNAME, (int channel, const char cname[256]));
@@ -776,22 +630,12 @@ class FakeWebRtcVoiceEngine
unsigned int& discardedPackets));
WEBRTC_STUB(GetRTCPStatistics, (int channel, webrtc::CallStatistics& stats));
WEBRTC_FUNC(SetREDStatus, (int channel, bool enable, int redPayloadtype)) {
- return SetFECStatus(channel, enable, redPayloadtype);
- }
- // TODO(minyue): remove the below function when transition to SetREDStatus
- // is finished.
- WEBRTC_FUNC(SetFECStatus, (int channel, bool enable, int redPayloadtype)) {
WEBRTC_CHECK_CHANNEL(channel);
channels_[channel]->red = enable;
channels_[channel]->red_type = redPayloadtype;
return 0;
}
WEBRTC_FUNC(GetREDStatus, (int channel, bool& enable, int& redPayloadtype)) {
- return GetFECStatus(channel, enable, redPayloadtype);
- }
- // TODO(minyue): remove the below function when transition to GetREDStatus
- // is finished.
- WEBRTC_FUNC(GetFECStatus, (int channel, bool& enable, int& redPayloadtype)) {
WEBRTC_CHECK_CHANNEL(channel);
enable = channels_[channel]->red;
redPayloadtype = channels_[channel]->red_type;
@@ -937,15 +781,6 @@ class FakeWebRtcVoiceEngine
void EnableStereoChannelSwapping(bool enable) {
stereo_swapping_enabled_ = enable;
}
- bool WasSendTelephoneEventCalled(int channel, int event_code, int length_ms) {
- return (channels_[channel]->dtmf_info.dtmf_event_code == event_code &&
- channels_[channel]->dtmf_info.dtmf_out_of_band == true &&
- channels_[channel]->dtmf_info.dtmf_length_ms == length_ms);
- }
- bool WasPlayDtmfToneCalled(int event_code, int length_ms) {
- return (dtmf_info_.dtmf_event_code == event_code &&
- dtmf_info_.dtmf_length_ms == length_ms);
- }
int GetNetEqCapacity() const {
auto ch = channels_.find(last_channel_);
ASSERT(ch != channels_.end());
@@ -958,47 +793,10 @@ class FakeWebRtcVoiceEngine
}
private:
- int GetNumDevices(int& num) {
-#ifdef WIN32
- num = 1;
-#else
- // On non-Windows platforms VE adds a special entry for the default device,
- // so if there is one physical device then there are two entries in the
- // list.
- num = 2;
-#endif
- return 0;
- }
-
- int GetDeviceName(int i, char* name, char* guid) {
- const char *s;
-#ifdef WIN32
- if (0 == i) {
- s = kFakeDeviceName;
- } else {
- return -1;
- }
-#else
- // See comment above.
- if (0 == i) {
- s = kFakeDefaultDeviceName;
- } else if (1 == i) {
- s = kFakeDeviceName;
- } else {
- return -1;
- }
-#endif
- strcpy(name, s);
- guid[0] = '\0';
- return 0;
- }
-
bool inited_;
int last_channel_;
std::map<int, Channel*> channels_;
bool fail_create_channel_;
- const cricket::AudioCodec* const* codecs_;
- int num_codecs_;
int num_set_send_codecs_; // how many times we call SetSendCodec().
bool ec_enabled_;
bool ec_metrics_enabled_;
@@ -1018,12 +816,9 @@ class FakeWebRtcVoiceEngine
int send_fail_channel_;
int recording_sample_rate_;
int playout_sample_rate_;
- DtmfInfo dtmf_info_;
FakeAudioProcessing audio_processing_;
};
-#undef WEBRTC_CHECK_HEADER_EXTENSION_ID
-
} // namespace cricket
#endif // TALK_SESSION_PHONE_FAKEWEBRTCVOICEENGINE_H_
diff --git a/talk/media/webrtc/simulcast.cc b/talk/media/webrtc/simulcast.cc
index f55d9606a5..b67a363a76 100755
--- a/talk/media/webrtc/simulcast.cc
+++ b/talk/media/webrtc/simulcast.cc
@@ -29,9 +29,11 @@
#include "talk/media/base/streamparams.h"
#include "talk/media/webrtc/simulcast.h"
+#include "webrtc/base/arraysize.h"
#include "webrtc/base/common.h"
#include "webrtc/base/logging.h"
#include "webrtc/system_wrappers/include/field_trial.h"
+
namespace cricket {
struct SimulcastFormat {
@@ -93,7 +95,7 @@ void MaybeExchangeWidthHeight(int* width, int* height) {
int FindSimulcastFormatIndex(int width, int height) {
MaybeExchangeWidthHeight(&width, &height);
- for (int i = 0; i < ARRAY_SIZE(kSimulcastFormats); ++i) {
+ for (int i = 0; i < arraysize(kSimulcastFormats); ++i) {
if (width >= kSimulcastFormats[i].width &&
height >= kSimulcastFormats[i].height) {
return i;
@@ -105,7 +107,7 @@ int FindSimulcastFormatIndex(int width, int height) {
int FindSimulcastFormatIndex(int width, int height, size_t max_layers) {
MaybeExchangeWidthHeight(&width, &height);
- for (int i = 0; i < ARRAY_SIZE(kSimulcastFormats); ++i) {
+ for (int i = 0; i < arraysize(kSimulcastFormats); ++i) {
if (width >= kSimulcastFormats[i].width &&
height >= kSimulcastFormats[i].height &&
max_layers == kSimulcastFormats[i].max_layers) {
diff --git a/talk/media/webrtc/webrtcmediaengine.cc b/talk/media/webrtc/webrtcmediaengine.cc
index af202bd613..31e5025a55 100644
--- a/talk/media/webrtc/webrtcmediaengine.cc
+++ b/talk/media/webrtc/webrtcmediaengine.cc
@@ -26,6 +26,9 @@
*/
#include "talk/media/webrtc/webrtcmediaengine.h"
+
+#include <algorithm>
+
#include "talk/media/webrtc/webrtcvideoengine2.h"
#include "talk/media/webrtc/webrtcvoiceengine.h"
@@ -68,44 +71,85 @@ MediaEngineInterface* WebRtcMediaEngineFactory::Create(
return CreateWebRtcMediaEngine(adm, encoder_factory, decoder_factory);
}
-const char* kBweExtensionPriorities[] = {
- kRtpTransportSequenceNumberHeaderExtension,
- kRtpAbsoluteSenderTimeHeaderExtension, kRtpTimestampOffsetHeaderExtension};
-
-const size_t kBweExtensionPrioritiesLength =
- ARRAY_SIZE(kBweExtensionPriorities);
+namespace {
+// Remove mutually exclusive extensions with lower priority.
+void DiscardRedundantExtensions(
+ std::vector<webrtc::RtpExtension>* extensions,
+ rtc::ArrayView<const char*> extensions_decreasing_prio) {
+ RTC_DCHECK(extensions);
+ bool found = false;
+ for (const char* name : extensions_decreasing_prio) {
+ auto it = std::find_if(extensions->begin(), extensions->end(),
+ [name](const webrtc::RtpExtension& rhs) {
+ return rhs.name == name;
+ });
+ if (it != extensions->end()) {
+ if (found) {
+ extensions->erase(it);
+ }
+ found = true;
+ }
+ }
+}
+} // namespace
-int GetPriority(const RtpHeaderExtension& extension,
- const char* extension_prios[],
- size_t extension_prios_length) {
- for (size_t i = 0; i < extension_prios_length; ++i) {
- if (extension.uri == extension_prios[i])
- return static_cast<int>(i);
+bool ValidateRtpExtensions(const std::vector<RtpHeaderExtension>& extensions) {
+ bool id_used[14] = {false};
+ for (const auto& extension : extensions) {
+ if (extension.id <= 0 || extension.id >= 15) {
+ LOG(LS_ERROR) << "Bad RTP extension ID: " << extension.ToString();
+ return false;
+ }
+ if (id_used[extension.id - 1]) {
+ LOG(LS_ERROR) << "Duplicate RTP extension ID: " << extension.ToString();
+ return false;
+ }
+ id_used[extension.id - 1] = true;
}
- return -1;
+ return true;
}
-std::vector<RtpHeaderExtension> FilterRedundantRtpExtensions(
+std::vector<webrtc::RtpExtension> FilterRtpExtensions(
const std::vector<RtpHeaderExtension>& extensions,
- const char* extension_prios[],
- size_t extension_prios_length) {
- if (extensions.empty())
- return std::vector<RtpHeaderExtension>();
- std::vector<RtpHeaderExtension> filtered;
- std::map<int, const RtpHeaderExtension*> sorted;
- for (auto& extension : extensions) {
- int priority =
- GetPriority(extension, extension_prios, extension_prios_length);
- if (priority == -1) {
- filtered.push_back(extension);
- continue;
+ bool (*supported)(const std::string&),
+ bool filter_redundant_extensions) {
+ RTC_DCHECK(ValidateRtpExtensions(extensions));
+ RTC_DCHECK(supported);
+ std::vector<webrtc::RtpExtension> result;
+
+ // Ignore any extensions that we don't recognize.
+ for (const auto& extension : extensions) {
+ if (supported(extension.uri)) {
+ result.push_back({extension.uri, extension.id});
} else {
- sorted[priority] = &extension;
+ LOG(LS_WARNING) << "Unsupported RTP extension: " << extension.ToString();
}
}
- if (!sorted.empty())
- filtered.push_back(*sorted.begin()->second);
- return filtered;
-}
+ // Sort by name, ascending, so that we don't reset extensions if they were
+ // specified in a different order (also allows us to use std::unique below).
+ std::sort(result.begin(), result.end(),
+ [](const webrtc::RtpExtension& rhs, const webrtc::RtpExtension& lhs) {
+ return rhs.name < lhs.name;
+ });
+
+ // Remove unnecessary extensions (used on send side).
+ if (filter_redundant_extensions) {
+ auto it = std::unique(result.begin(), result.end(),
+ [](const webrtc::RtpExtension& rhs, const webrtc::RtpExtension& lhs) {
+ return rhs.name == lhs.name;
+ });
+ result.erase(it, result.end());
+
+ // Keep just the highest priority extension of any in the following list.
+ static const char* kBweExtensionPriorities[] = {
+ kRtpTransportSequenceNumberHeaderExtension,
+ kRtpAbsoluteSenderTimeHeaderExtension,
+ kRtpTimestampOffsetHeaderExtension
+ };
+ DiscardRedundantExtensions(&result, kBweExtensionPriorities);
+ }
+
+ return result;
+}
} // namespace cricket
diff --git a/talk/media/webrtc/webrtcmediaengine.h b/talk/media/webrtc/webrtcmediaengine.h
index 8d7540404d..831d0725e8 100644
--- a/talk/media/webrtc/webrtcmediaengine.h
+++ b/talk/media/webrtc/webrtcmediaengine.h
@@ -28,7 +28,11 @@
#ifndef TALK_MEDIA_WEBRTCMEDIAENGINE_H_
#define TALK_MEDIA_WEBRTCMEDIAENGINE_H_
+#include <string>
+#include <vector>
+
#include "talk/media/base/mediaengine.h"
+#include "webrtc/config.h"
namespace webrtc {
class AudioDeviceModule;
@@ -48,13 +52,18 @@ class WebRtcMediaEngineFactory {
WebRtcVideoDecoderFactory* decoder_factory);
};
-extern const char* kBweExtensionPriorities[];
-extern const size_t kBweExtensionPrioritiesLength;
+// Verify that extension IDs are within 1-byte extension range and are not
+// overlapping.
+bool ValidateRtpExtensions(const std::vector<RtpHeaderExtension>& extensions);
-std::vector<RtpHeaderExtension> FilterRedundantRtpExtensions(
+// Convert cricket::RtpHeaderExtension:s to webrtc::RtpExtension:s, discarding
+// any extensions not validated by the 'supported' predicate. Duplicate
+// extensions are removed if 'filter_redundant_extensions' is set, and also any
+// mutually exclusive extensions (see implementation for details).
+std::vector<webrtc::RtpExtension> FilterRtpExtensions(
const std::vector<RtpHeaderExtension>& extensions,
- const char* extension_prios[],
- size_t extension_prios_length);
+ bool (*supported)(const std::string&),
+ bool filter_redundant_extensions);
} // namespace cricket
diff --git a/talk/media/webrtc/webrtcmediaengine_unittest.cc b/talk/media/webrtc/webrtcmediaengine_unittest.cc
new file mode 100644
index 0000000000..7c80e77301
--- /dev/null
+++ b/talk/media/webrtc/webrtcmediaengine_unittest.cc
@@ -0,0 +1,205 @@
+/*
+ * libjingle
+ * Copyright 2015 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+#include "talk/media/webrtc/webrtcmediaengine.h"
+
+namespace cricket {
+namespace {
+
+std::vector<RtpHeaderExtension> MakeUniqueExtensions() {
+ std::vector<RtpHeaderExtension> result;
+ char name[] = "a";
+ for (int i = 0; i < 7; ++i) {
+ result.push_back(RtpHeaderExtension(name, 1 + i));
+ name[0]++;
+ result.push_back(RtpHeaderExtension(name, 14 - i));
+ name[0]++;
+ }
+ return result;
+}
+
+std::vector<RtpHeaderExtension> MakeRedundantExtensions() {
+ std::vector<RtpHeaderExtension> result;
+ char name[] = "a";
+ for (int i = 0; i < 7; ++i) {
+ result.push_back(RtpHeaderExtension(name, 1 + i));
+ result.push_back(RtpHeaderExtension(name, 14 - i));
+ name[0]++;
+ }
+ return result;
+}
+
+bool SupportedExtensions1(const std::string& name) {
+ return name == "c" || name == "i";
+}
+
+bool SupportedExtensions2(const std::string& name) {
+ return name != "a" && name != "n";
+}
+
+bool IsSorted(const std::vector<webrtc::RtpExtension>& extensions) {
+ const std::string* last = nullptr;
+ for (const auto& extension : extensions) {
+ if (last && *last > extension.name) {
+ return false;
+ }
+ last = &extension.name;
+ }
+ return true;
+}
+} // namespace
+
+TEST(WebRtcMediaEngineTest, ValidateRtpExtensions_EmptyList) {
+ std::vector<RtpHeaderExtension> extensions;
+ EXPECT_TRUE(ValidateRtpExtensions(extensions));
+}
+
+TEST(WebRtcMediaEngineTest, ValidateRtpExtensions_AllGood) {
+ std::vector<RtpHeaderExtension> extensions = MakeUniqueExtensions();
+ EXPECT_TRUE(ValidateRtpExtensions(extensions));
+}
+
+TEST(WebRtcMediaEngineTest, ValidateRtpExtensions_OutOfRangeId_Low) {
+ std::vector<RtpHeaderExtension> extensions = MakeUniqueExtensions();
+ extensions.push_back(RtpHeaderExtension("foo", 0));
+ EXPECT_FALSE(ValidateRtpExtensions(extensions));
+}
+
+TEST(WebRtcMediaEngineTest, ValidateRtpExtensions_OutOfRangeId_High) {
+ std::vector<RtpHeaderExtension> extensions = MakeUniqueExtensions();
+ extensions.push_back(RtpHeaderExtension("foo", 15));
+ EXPECT_FALSE(ValidateRtpExtensions(extensions));
+}
+
+TEST(WebRtcMediaEngineTest, ValidateRtpExtensions_OverlappingIds_StartOfSet) {
+ std::vector<RtpHeaderExtension> extensions = MakeUniqueExtensions();
+ extensions.push_back(RtpHeaderExtension("foo", 1));
+ EXPECT_FALSE(ValidateRtpExtensions(extensions));
+}
+
+TEST(WebRtcMediaEngineTest, ValidateRtpExtensions_OverlappingIds_EndOfSet) {
+ std::vector<RtpHeaderExtension> extensions = MakeUniqueExtensions();
+ extensions.push_back(RtpHeaderExtension("foo", 14));
+ EXPECT_FALSE(ValidateRtpExtensions(extensions));
+}
+
+TEST(WebRtcMediaEngineTest, FilterRtpExtensions_EmptyList) {
+ std::vector<RtpHeaderExtension> extensions;
+ std::vector<webrtc::RtpExtension> filtered =
+ FilterRtpExtensions(extensions, SupportedExtensions1, true);
+ EXPECT_EQ(0, filtered.size());
+}
+
+TEST(WebRtcMediaEngineTest, FilterRtpExtensions_IncludeOnlySupported) {
+ std::vector<RtpHeaderExtension> extensions = MakeUniqueExtensions();
+ std::vector<webrtc::RtpExtension> filtered =
+ FilterRtpExtensions(extensions, SupportedExtensions1, false);
+ EXPECT_EQ(2, filtered.size());
+ EXPECT_EQ("c", filtered[0].name);
+ EXPECT_EQ("i", filtered[1].name);
+}
+
+TEST(WebRtcMediaEngineTest, FilterRtpExtensions_SortedByName_1) {
+ std::vector<RtpHeaderExtension> extensions = MakeUniqueExtensions();
+ std::vector<webrtc::RtpExtension> filtered =
+ FilterRtpExtensions(extensions, SupportedExtensions2, false);
+ EXPECT_EQ(12, filtered.size());
+ EXPECT_TRUE(IsSorted(filtered));
+}
+
+TEST(WebRtcMediaEngineTest, FilterRtpExtensions_SortedByName_2) {
+ std::vector<RtpHeaderExtension> extensions = MakeUniqueExtensions();
+ std::vector<webrtc::RtpExtension> filtered =
+ FilterRtpExtensions(extensions, SupportedExtensions2, true);
+ EXPECT_EQ(12, filtered.size());
+ EXPECT_TRUE(IsSorted(filtered));
+}
+
+TEST(WebRtcMediaEngineTest, FilterRtpExtensions_DontRemoveRedundant) {
+ std::vector<RtpHeaderExtension> extensions = MakeRedundantExtensions();
+ std::vector<webrtc::RtpExtension> filtered =
+ FilterRtpExtensions(extensions, SupportedExtensions2, false);
+ EXPECT_EQ(12, filtered.size());
+ EXPECT_TRUE(IsSorted(filtered));
+ EXPECT_EQ(filtered[0].name, filtered[1].name);
+}
+
+TEST(WebRtcMediaEngineTest, FilterRtpExtensions_RemoveRedundant) {
+ std::vector<RtpHeaderExtension> extensions = MakeRedundantExtensions();
+ std::vector<webrtc::RtpExtension> filtered =
+ FilterRtpExtensions(extensions, SupportedExtensions2, true);
+ EXPECT_EQ(6, filtered.size());
+ EXPECT_TRUE(IsSorted(filtered));
+ EXPECT_NE(filtered[0].name, filtered[1].name);
+}
+
+TEST(WebRtcMediaEngineTest, FilterRtpExtensions_RemoveRedundantBwe_1) {
+ std::vector<RtpHeaderExtension> extensions;
+ extensions.push_back(
+ RtpHeaderExtension(kRtpTransportSequenceNumberHeaderExtension, 3));
+ extensions.push_back(
+ RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, 9));
+ extensions.push_back(
+ RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension, 6));
+ extensions.push_back(
+ RtpHeaderExtension(kRtpTransportSequenceNumberHeaderExtension, 1));
+ extensions.push_back(
+ RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, 14));
+ std::vector<webrtc::RtpExtension> filtered =
+ FilterRtpExtensions(extensions, SupportedExtensions2, true);
+ EXPECT_EQ(1, filtered.size());
+ EXPECT_EQ(kRtpTransportSequenceNumberHeaderExtension, filtered[0].name);
+}
+
+TEST(WebRtcMediaEngineTest, FilterRtpExtensions_RemoveRedundantBwe_2) {
+ std::vector<RtpHeaderExtension> extensions;
+ extensions.push_back(
+ RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, 1));
+ extensions.push_back(
+ RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension, 14));
+ extensions.push_back(
+ RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, 7));
+ std::vector<webrtc::RtpExtension> filtered =
+ FilterRtpExtensions(extensions, SupportedExtensions2, true);
+ EXPECT_EQ(1, filtered.size());
+ EXPECT_EQ(kRtpAbsoluteSenderTimeHeaderExtension, filtered[0].name);
+}
+
+TEST(WebRtcMediaEngineTest, FilterRtpExtensions_RemoveRedundantBwe_3) {
+ std::vector<RtpHeaderExtension> extensions;
+ extensions.push_back(
+ RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, 2));
+ extensions.push_back(
+ RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, 14));
+ std::vector<webrtc::RtpExtension> filtered =
+ FilterRtpExtensions(extensions, SupportedExtensions2, true);
+ EXPECT_EQ(1, filtered.size());
+ EXPECT_EQ(kRtpTimestampOffsetHeaderExtension, filtered[0].name);
+}
+} // namespace cricket
diff --git a/talk/media/webrtc/webrtcvideocapturer.cc b/talk/media/webrtc/webrtcvideocapturer.cc
index 7d72128d61..ee4db5b1d2 100644
--- a/talk/media/webrtc/webrtcvideocapturer.cc
+++ b/talk/media/webrtc/webrtcvideocapturer.cc
@@ -34,6 +34,7 @@
#ifdef HAVE_WEBRTC_VIDEO
#include "talk/media/webrtc/webrtcvideoframe.h"
#include "talk/media/webrtc/webrtcvideoframefactory.h"
+#include "webrtc/base/arraysize.h"
#include "webrtc/base/bind.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/criticalsection.h"
@@ -43,7 +44,7 @@
#include "webrtc/base/timeutils.h"
#include "webrtc/base/win32.h" // Need this to #include the impl files.
-#include "webrtc/modules/video_capture/include/video_capture_factory.h"
+#include "webrtc/modules/video_capture/video_capture_factory.h"
#include "webrtc/system_wrappers/include/field_trial.h"
namespace cricket {
@@ -83,7 +84,7 @@ class WebRtcVcmFactory : public WebRtcVcmFactoryInterface {
static bool CapabilityToFormat(const webrtc::VideoCaptureCapability& cap,
VideoFormat* format) {
uint32_t fourcc = 0;
- for (size_t i = 0; i < ARRAY_SIZE(kSupportedFourCCs); ++i) {
+ for (size_t i = 0; i < arraysize(kSupportedFourCCs); ++i) {
if (kSupportedFourCCs[i].webrtc_type == cap.rawType) {
fourcc = kSupportedFourCCs[i].fourcc;
break;
@@ -103,7 +104,7 @@ static bool CapabilityToFormat(const webrtc::VideoCaptureCapability& cap,
static bool FormatToCapability(const VideoFormat& format,
webrtc::VideoCaptureCapability* cap) {
webrtc::RawVideoType webrtc_type = webrtc::kVideoUnknown;
- for (size_t i = 0; i < ARRAY_SIZE(kSupportedFourCCs); ++i) {
+ for (size_t i = 0; i < arraysize(kSupportedFourCCs); ++i) {
if (kSupportedFourCCs[i].fourcc == format.fourcc) {
webrtc_type = kSupportedFourCCs[i].webrtc_type;
break;
@@ -171,8 +172,8 @@ bool WebRtcVideoCapturer::Init(const Device& device) {
bool found = false;
for (int index = 0; index < num_cams; ++index) {
char vcm_name[256];
- if (info->GetDeviceName(index, vcm_name, ARRAY_SIZE(vcm_name),
- vcm_id, ARRAY_SIZE(vcm_id)) != -1) {
+ if (info->GetDeviceName(index, vcm_name, arraysize(vcm_name), vcm_id,
+ arraysize(vcm_id)) != -1) {
if (device.name == reinterpret_cast<char*>(vcm_name)) {
found = true;
break;
@@ -349,6 +350,7 @@ void WebRtcVideoCapturer::Stop() {
SetCaptureFormat(NULL);
start_thread_ = nullptr;
+ SetCaptureState(CS_STOPPED);
}
bool WebRtcVideoCapturer::IsRunning() {
@@ -361,7 +363,7 @@ bool WebRtcVideoCapturer::GetPreferredFourccs(std::vector<uint32_t>* fourccs) {
}
fourccs->clear();
- for (size_t i = 0; i < ARRAY_SIZE(kSupportedFourCCs); ++i) {
+ for (size_t i = 0; i < arraysize(kSupportedFourCCs); ++i) {
fourccs->push_back(kSupportedFourCCs[i].fourcc);
}
return true;
diff --git a/talk/media/webrtc/webrtcvideocapturer.h b/talk/media/webrtc/webrtcvideocapturer.h
index 0a99884fe1..591e46f629 100644
--- a/talk/media/webrtc/webrtcvideocapturer.h
+++ b/talk/media/webrtc/webrtcvideocapturer.h
@@ -39,7 +39,7 @@
#include "webrtc/base/messagehandler.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
-#include "webrtc/modules/video_capture/include/video_capture.h"
+#include "webrtc/modules/video_capture/video_capture.h"
namespace cricket {
diff --git a/talk/media/webrtc/webrtcvideocapturer_unittest.cc b/talk/media/webrtc/webrtcvideocapturer_unittest.cc
index d560fc554e..85db32e7d2 100644
--- a/talk/media/webrtc/webrtcvideocapturer_unittest.cc
+++ b/talk/media/webrtc/webrtcvideocapturer_unittest.cc
@@ -111,6 +111,7 @@ TEST_F(WebRtcVideoCapturerTest, TestCapture) {
capturer_->Stop();
EXPECT_FALSE(capturer_->IsRunning());
EXPECT_TRUE(capturer_->GetCaptureFormat() == NULL);
+ EXPECT_EQ_WAIT(cricket::CS_STOPPED, listener_.last_capture_state(), 1000);
}
TEST_F(WebRtcVideoCapturerTest, TestCaptureVcm) {
diff --git a/talk/media/webrtc/webrtcvideoengine2.cc b/talk/media/webrtc/webrtcvideoengine2.cc
index bcd513ee2d..55c07426d0 100644
--- a/talk/media/webrtc/webrtcvideoengine2.cc
+++ b/talk/media/webrtc/webrtcvideoengine2.cc
@@ -152,9 +152,7 @@ bool CodecIsInternallySupported(const std::string& codec_name) {
return true;
}
if (CodecNamesEq(codec_name, kVp9CodecName)) {
- const std::string group_name =
- webrtc::field_trial::FindFullName("WebRTC-SupportVP9");
- return group_name == "Enabled" || group_name == "EnabledByFlag";
+ return true;
}
if (CodecNamesEq(codec_name, kH264CodecName)) {
return webrtc::H264Encoder::IsSupported() &&
@@ -168,6 +166,8 @@ void AddDefaultFeedbackParams(VideoCodec* codec) {
codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamNack, kParamValueEmpty));
codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamNack, kRtcpFbNackParamPli));
codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamRemb, kParamValueEmpty));
+ codec->AddFeedbackParam(
+ FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty));
}
static VideoCodec MakeVideoCodecWithDefaultFeedbackParams(int payload_type,
@@ -243,20 +243,6 @@ static bool ValidateStreamParams(const StreamParams& sp) {
return true;
}
-static std::string RtpExtensionsToString(
- const std::vector<RtpHeaderExtension>& extensions) {
- std::stringstream out;
- out << '{';
- for (size_t i = 0; i < extensions.size(); ++i) {
- out << "{" << extensions[i].uri << ": " << extensions[i].id << "}";
- if (i != extensions.size() - 1) {
- out << ", ";
- }
- }
- out << '}';
- return out.str();
-}
-
inline const webrtc::RtpExtension* FindHeaderExtension(
const std::vector<webrtc::RtpExtension>& extensions,
const std::string& name) {
@@ -303,7 +289,8 @@ static void MergeFecConfig(const webrtc::FecConfig& other,
// Returns true if the given codec is disallowed from doing simulcast.
bool IsCodecBlacklistedForSimulcast(const std::string& codec_name) {
- return CodecNamesEq(codec_name, kH264CodecName);
+ return CodecNamesEq(codec_name, kH264CodecName) ||
+ CodecNamesEq(codec_name, kVp9CodecName);
}
// The selected thresholds for QVGA and VGA corresponded to a QP around 10.
@@ -339,13 +326,13 @@ static const int kDefaultRtcpReceiverReportSsrc = 1;
std::vector<VideoCodec> DefaultVideoCodecList() {
std::vector<VideoCodec> codecs;
+ codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(kDefaultVp8PlType,
+ kVp8CodecName));
if (CodecIsInternallySupported(kVp9CodecName)) {
codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(kDefaultVp9PlType,
kVp9CodecName));
// TODO(andresp): Add rtx codec for vp9 and verify it works.
}
- codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(kDefaultVp8PlType,
- kVp8CodecName));
if (CodecIsInternallySupported(kH264CodecName)) {
codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(kDefaultH264PlType,
kH264CodecName));
@@ -357,72 +344,6 @@ std::vector<VideoCodec> DefaultVideoCodecList() {
return codecs;
}
-static bool FindFirstMatchingCodec(const std::vector<VideoCodec>& codecs,
- const VideoCodec& requested_codec,
- VideoCodec* matching_codec) {
- for (size_t i = 0; i < codecs.size(); ++i) {
- if (requested_codec.Matches(codecs[i])) {
- *matching_codec = codecs[i];
- return true;
- }
- }
- return false;
-}
-
-static bool ValidateRtpHeaderExtensionIds(
- const std::vector<RtpHeaderExtension>& extensions) {
- std::set<int> extensions_used;
- for (size_t i = 0; i < extensions.size(); ++i) {
- if (extensions[i].id <= 0 || extensions[i].id >= 15 ||
- !extensions_used.insert(extensions[i].id).second) {
- LOG(LS_ERROR) << "RTP extensions are with incorrect or duplicate ids.";
- return false;
- }
- }
- return true;
-}
-
-static bool CompareRtpHeaderExtensionIds(
- const webrtc::RtpExtension& extension1,
- const webrtc::RtpExtension& extension2) {
- // Sorting on ID is sufficient, more than one extension per ID is unsupported.
- return extension1.id > extension2.id;
-}
-
-static std::vector<webrtc::RtpExtension> FilterRtpExtensions(
- const std::vector<RtpHeaderExtension>& extensions) {
- std::vector<webrtc::RtpExtension> webrtc_extensions;
- for (size_t i = 0; i < extensions.size(); ++i) {
- // Unsupported extensions will be ignored.
- if (webrtc::RtpExtension::IsSupportedForVideo(extensions[i].uri)) {
- webrtc_extensions.push_back(webrtc::RtpExtension(
- extensions[i].uri, extensions[i].id));
- } else {
- LOG(LS_WARNING) << "Unsupported RTP extension: " << extensions[i].uri;
- }
- }
-
- // Sort filtered headers to make sure that they can later be compared
- // regardless of in which order they were entered.
- std::sort(webrtc_extensions.begin(), webrtc_extensions.end(),
- CompareRtpHeaderExtensionIds);
- return webrtc_extensions;
-}
-
-static bool RtpExtensionsHaveChanged(
- const std::vector<webrtc::RtpExtension>& before,
- const std::vector<webrtc::RtpExtension>& after) {
- if (before.size() != after.size())
- return true;
- for (size_t i = 0; i < before.size(); ++i) {
- if (before[i].id != after[i].id)
- return true;
- if (before[i].name != after[i].name)
- return true;
- }
- return false;
-}
-
std::vector<webrtc::VideoStream>
WebRtcVideoChannel2::WebRtcVideoSendStream::CreateSimulcastVideoStreams(
const VideoCodec& codec,
@@ -489,7 +410,8 @@ void* WebRtcVideoChannel2::WebRtcVideoSendStream::ConfigureVideoEncoderSettings(
denoising = false;
} else {
// Use codec default if video_noise_reduction is unset.
- codec_default_denoising = !options.video_noise_reduction.Get(&denoising);
+ codec_default_denoising = !options.video_noise_reduction;
+ denoising = options.video_noise_reduction.value_or(false);
}
if (CodecNamesEq(codec.name, kVp8CodecName)) {
@@ -554,20 +476,6 @@ WebRtcVideoEngine2::WebRtcVideoEngine2()
external_encoder_factory_(NULL) {
LOG(LS_INFO) << "WebRtcVideoEngine2::WebRtcVideoEngine2()";
video_codecs_ = GetSupportedCodecs();
- rtp_header_extensions_.push_back(
- RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension,
- kRtpTimestampOffsetHeaderExtensionDefaultId));
- rtp_header_extensions_.push_back(
- RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension,
- kRtpAbsoluteSenderTimeHeaderExtensionDefaultId));
- rtp_header_extensions_.push_back(
- RtpHeaderExtension(kRtpVideoRotationHeaderExtension,
- kRtpVideoRotationHeaderExtensionDefaultId));
- if (webrtc::field_trial::FindFullName("WebRTC-SendSideBwe") == "Enabled") {
- rtp_header_extensions_.push_back(RtpHeaderExtension(
- kRtpTransportSequenceNumberHeaderExtension,
- kRtpTransportSequenceNumberHeaderExtensionDefaultId));
- }
}
WebRtcVideoEngine2::~WebRtcVideoEngine2() {
@@ -579,29 +487,6 @@ void WebRtcVideoEngine2::Init() {
initialized_ = true;
}
-bool WebRtcVideoEngine2::SetDefaultEncoderConfig(
- const VideoEncoderConfig& config) {
- const VideoCodec& codec = config.max_codec;
- bool supports_codec = false;
- for (size_t i = 0; i < video_codecs_.size(); ++i) {
- if (CodecNamesEq(video_codecs_[i].name, codec.name)) {
- video_codecs_[i].width = codec.width;
- video_codecs_[i].height = codec.height;
- video_codecs_[i].framerate = codec.framerate;
- supports_codec = true;
- break;
- }
- }
-
- if (!supports_codec) {
- LOG(LS_ERROR) << "SetDefaultEncoderConfig, codec not supported: "
- << codec.ToString();
- return false;
- }
-
- return true;
-}
-
WebRtcVideoChannel2* WebRtcVideoEngine2::CreateChannel(
webrtc::Call* call,
const VideoOptions& options) {
@@ -615,19 +500,23 @@ const std::vector<VideoCodec>& WebRtcVideoEngine2::codecs() const {
return video_codecs_;
}
-const std::vector<RtpHeaderExtension>&
-WebRtcVideoEngine2::rtp_header_extensions() const {
- return rtp_header_extensions_;
-}
-
-void WebRtcVideoEngine2::SetLogging(int min_sev, const char* filter) {
- // TODO(pbos): Set up logging.
- LOG(LS_VERBOSE) << "SetLogging: " << min_sev << '"' << filter << '"';
- // if min_sev == -1, we keep the current log level.
- if (min_sev < 0) {
- RTC_DCHECK(min_sev == -1);
- return;
+RtpCapabilities WebRtcVideoEngine2::GetCapabilities() const {
+ RtpCapabilities capabilities;
+ capabilities.header_extensions.push_back(
+ RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension,
+ kRtpTimestampOffsetHeaderExtensionDefaultId));
+ capabilities.header_extensions.push_back(
+ RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension,
+ kRtpAbsoluteSenderTimeHeaderExtensionDefaultId));
+ capabilities.header_extensions.push_back(
+ RtpHeaderExtension(kRtpVideoRotationHeaderExtension,
+ kRtpVideoRotationHeaderExtensionDefaultId));
+ if (webrtc::field_trial::FindFullName("WebRTC-SendSideBwe") == "Enabled") {
+ capabilities.header_extensions.push_back(RtpHeaderExtension(
+ kRtpTransportSequenceNumberHeaderExtension,
+ kRtpTransportSequenceNumberHeaderExtensionDefaultId));
}
+ return capabilities;
}
void WebRtcVideoEngine2::SetExternalDecoderFactory(
@@ -677,48 +566,6 @@ bool WebRtcVideoEngine2::FindCodec(const VideoCodec& in) {
return false;
}
-// Tells whether the |requested| codec can be transmitted or not. If it can be
-// transmitted |out| is set with the best settings supported. Aspect ratio will
-// be set as close to |current|'s as possible. If not set |requested|'s
-// dimensions will be used for aspect ratio matching.
-bool WebRtcVideoEngine2::CanSendCodec(const VideoCodec& requested,
- const VideoCodec& current,
- VideoCodec* out) {
- RTC_DCHECK(out != NULL);
-
- if (requested.width != requested.height &&
- (requested.height == 0 || requested.width == 0)) {
- // 0xn and nx0 are invalid resolutions.
- return false;
- }
-
- VideoCodec matching_codec;
- if (!FindFirstMatchingCodec(video_codecs_, requested, &matching_codec)) {
- // Codec not supported.
- return false;
- }
-
- out->id = requested.id;
- out->name = requested.name;
- out->preference = requested.preference;
- out->params = requested.params;
- out->framerate = std::min(requested.framerate, matching_codec.framerate);
- out->params = requested.params;
- out->feedback_params = requested.feedback_params;
- out->width = requested.width;
- out->height = requested.height;
- if (requested.width == 0 && requested.height == 0) {
- return true;
- }
-
- while (out->width > matching_codec.width) {
- out->width /= 2;
- out->height /= 2;
- }
-
- return out->width > 0 && out->height > 0;
-}
-
// Ignore spammy trace messages, mostly from the stats API when we haven't
// gotten RTCP info yet from the remote side.
bool WebRtcVideoEngine2::ShouldIgnoreTrace(const std::string& trace) {
@@ -777,7 +624,8 @@ WebRtcVideoChannel2::WebRtcVideoChannel2(
RTC_DCHECK(thread_checker_.CalledOnValidThread());
SetDefaultOptions();
options_.SetAll(options);
- options_.cpu_overuse_detection.Get(&signal_cpu_adaptation_);
+ if (options_.cpu_overuse_detection)
+ signal_cpu_adaptation_ = *options_.cpu_overuse_detection;
rtcp_receiver_report_ssrc_ = kDefaultRtcpReceiverReportSsrc;
sending_ = false;
default_send_ssrc_ = 0;
@@ -785,10 +633,10 @@ WebRtcVideoChannel2::WebRtcVideoChannel2(
}
void WebRtcVideoChannel2::SetDefaultOptions() {
- options_.cpu_overuse_detection.Set(true);
- options_.dscp.Set(false);
- options_.suspend_below_min_bitrate.Set(false);
- options_.screencast_min_bitrate.Set(0);
+ options_.cpu_overuse_detection = rtc::Optional<bool>(true);
+ options_.dscp = rtc::Optional<bool>(false);
+ options_.suspend_below_min_bitrate = rtc::Optional<bool>(false);
+ options_.screencast_min_bitrate = rtc::Optional<int>(0);
}
WebRtcVideoChannel2::~WebRtcVideoChannel2() {
@@ -863,19 +711,43 @@ bool WebRtcVideoChannel2::ReceiveCodecsHaveChanged(
}
bool WebRtcVideoChannel2::SetSendParameters(const VideoSendParameters& params) {
+ TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetSendParameters");
+ LOG(LS_INFO) << "SetSendParameters: " << params.ToString();
// TODO(pbos): Refactor this to only recreate the send streams once
// instead of 4 times.
- return (SetSendCodecs(params.codecs) &&
- SetSendRtpHeaderExtensions(params.extensions) &&
- SetMaxSendBandwidth(params.max_bandwidth_bps) &&
- SetOptions(params.options));
+ if (!SetSendCodecs(params.codecs) ||
+ !SetSendRtpHeaderExtensions(params.extensions) ||
+ !SetMaxSendBandwidth(params.max_bandwidth_bps) ||
+ !SetOptions(params.options)) {
+ return false;
+ }
+ if (send_params_.rtcp.reduced_size != params.rtcp.reduced_size) {
+ rtc::CritScope stream_lock(&stream_crit_);
+ for (auto& kv : send_streams_) {
+ kv.second->SetSendParameters(params);
+ }
+ }
+ send_params_ = params;
+ return true;
}
bool WebRtcVideoChannel2::SetRecvParameters(const VideoRecvParameters& params) {
+ TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetRecvParameters");
+ LOG(LS_INFO) << "SetRecvParameters: " << params.ToString();
// TODO(pbos): Refactor this to only recreate the recv streams once
// instead of twice.
- return (SetRecvCodecs(params.codecs) &&
- SetRecvRtpHeaderExtensions(params.extensions));
+ if (!SetRecvCodecs(params.codecs) ||
+ !SetRecvRtpHeaderExtensions(params.extensions)) {
+ return false;
+ }
+ if (recv_params_.rtcp.reduced_size != params.rtcp.reduced_size) {
+ rtc::CritScope stream_lock(&stream_crit_);
+ for (auto& kv : receive_streams_) {
+ kv.second->SetRecvParameters(params);
+ }
+ }
+ recv_params_ = params;
+ return true;
}
std::string WebRtcVideoChannel2::CodecSettingsVectorToString(
@@ -952,15 +824,15 @@ bool WebRtcVideoChannel2::SetSendCodecs(const std::vector<VideoCodec>& codecs) {
LOG(LS_INFO) << "Using codec: " << supported_codecs.front().codec.ToString();
- VideoCodecSettings old_codec;
- if (send_codec_.Get(&old_codec) && supported_codecs.front() == old_codec) {
+ if (send_codec_ && supported_codecs.front() == *send_codec_) {
LOG(LS_INFO) << "Ignore call to SetSendCodecs because first supported "
"codec hasn't changed.";
// Using same codec, avoid reconfiguring.
return true;
}
- send_codec_.Set(supported_codecs.front());
+ send_codec_ = rtc::Optional<WebRtcVideoChannel2::VideoCodecSettings>(
+ supported_codecs.front());
rtc::CritScope stream_lock(&stream_crit_);
LOG(LS_INFO) << "Change the send codec because SetSendCodecs has a different "
@@ -969,12 +841,15 @@ bool WebRtcVideoChannel2::SetSendCodecs(const std::vector<VideoCodec>& codecs) {
RTC_DCHECK(kv.second != nullptr);
kv.second->SetCodec(supported_codecs.front());
}
- LOG(LS_INFO) << "SetNackAndRemb on all the receive streams because the send "
- "codec has changed.";
+ LOG(LS_INFO)
+ << "SetFeedbackOptions on all the receive streams because the send "
+ "codec has changed.";
for (auto& kv : receive_streams_) {
RTC_DCHECK(kv.second != nullptr);
- kv.second->SetNackAndRemb(HasNack(supported_codecs.front().codec),
- HasRemb(supported_codecs.front().codec));
+ kv.second->SetFeedbackParameters(
+ HasNack(supported_codecs.front().codec),
+ HasRemb(supported_codecs.front().codec),
+ HasTransportCc(supported_codecs.front().codec));
}
// TODO(holmer): Changing the codec parameters shouldn't necessarily mean that
@@ -1006,12 +881,11 @@ bool WebRtcVideoChannel2::SetSendCodecs(const std::vector<VideoCodec>& codecs) {
}
bool WebRtcVideoChannel2::GetSendCodec(VideoCodec* codec) {
- VideoCodecSettings codec_settings;
- if (!send_codec_.Get(&codec_settings)) {
+ if (!send_codec_) {
LOG(LS_VERBOSE) << "GetSendCodec: No send codec set.";
return false;
}
- *codec = codec_settings.codec;
+ *codec = send_codec_->codec;
return true;
}
@@ -1028,7 +902,7 @@ bool WebRtcVideoChannel2::SetSendStreamFormat(uint32_t ssrc,
bool WebRtcVideoChannel2::SetSend(bool send) {
LOG(LS_VERBOSE) << "SetSend: " << (send ? "true" : "false");
- if (send && !send_codec_.IsSet()) {
+ if (send && !send_codec_) {
LOG(LS_ERROR) << "SetSend(true) called before setting codec.";
return false;
}
@@ -1094,15 +968,10 @@ bool WebRtcVideoChannel2::AddSendStream(const StreamParams& sp) {
webrtc::VideoSendStream::Config config(this);
config.overuse_callback = this;
- WebRtcVideoSendStream* stream =
- new WebRtcVideoSendStream(call_,
- sp,
- config,
- external_encoder_factory_,
- options_,
- bitrate_config_.max_bitrate_bps,
- send_codec_,
- send_rtp_extensions_);
+ WebRtcVideoSendStream* stream = new WebRtcVideoSendStream(
+ call_, sp, config, external_encoder_factory_, options_,
+ bitrate_config_.max_bitrate_bps, send_codec_, send_rtp_extensions_,
+ send_params_);
uint32_t ssrc = sp.first_ssrc();
RTC_DCHECK(ssrc != 0);
@@ -1224,15 +1093,13 @@ bool WebRtcVideoChannel2::AddRecvStream(const StreamParams& sp,
// Set up A/V sync group based on sync label.
config.sync_group = sp.sync_label;
- config.rtp.remb = false;
- VideoCodecSettings send_codec;
- if (send_codec_.Get(&send_codec)) {
- config.rtp.remb = HasRemb(send_codec.codec);
- }
+ config.rtp.remb = send_codec_ ? HasRemb(send_codec_->codec) : false;
+ config.rtp.transport_cc =
+ send_codec_ ? HasTransportCc(send_codec_->codec) : false;
receive_streams_[ssrc] = new WebRtcVideoReceiveStream(
call_, sp, config, external_decoder_factory_, default_stream,
- recv_codecs_);
+ recv_codecs_, options_.disable_prerenderer_smoothing.value_or(false));
return true;
}
@@ -1246,6 +1113,9 @@ void WebRtcVideoChannel2::ConfigureReceiverRtp(
config->rtp.local_ssrc = rtcp_receiver_report_ssrc_;
config->rtp.extensions = recv_rtp_extensions_;
+ config->rtp.rtcp_mode = recv_params_.rtcp.reduced_size
+ ? webrtc::RtcpMode::kReducedSize
+ : webrtc::RtcpMode::kCompound;
// TODO(pbos): This protection is against setting the same local ssrc as
// remote which is not permitted by the lower-level API. RTCP requires a
@@ -1482,12 +1352,14 @@ void WebRtcVideoChannel2::OnRtcpReceived(
const rtc::PacketTime& packet_time) {
const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
packet_time.not_before);
- if (call_->Receiver()->DeliverPacket(
- webrtc::MediaType::VIDEO,
- reinterpret_cast<const uint8_t*>(packet->data()), packet->size(),
- webrtc_packet_time) != webrtc::PacketReceiver::DELIVERY_OK) {
- LOG(LS_WARNING) << "Failed to deliver RTCP packet.";
- }
+ // TODO(pbos): Check webrtc::PacketReceiver::DELIVERY_OK once we deliver
+ // for both audio and video on the same path. Since BundleFilter doesn't
+ // filter RTCP anymore incoming RTCP packets could've been going to audio (so
+ // logging failures spam the log).
+ call_->Receiver()->DeliverPacket(
+ webrtc::MediaType::VIDEO,
+ reinterpret_cast<const uint8_t*>(packet->data()), packet->size(),
+ webrtc_packet_time);
}
void WebRtcVideoChannel2::OnReadyToSend(bool ready) {
@@ -1512,20 +1384,17 @@ bool WebRtcVideoChannel2::MuteStream(uint32_t ssrc, bool mute) {
bool WebRtcVideoChannel2::SetRecvRtpHeaderExtensions(
const std::vector<RtpHeaderExtension>& extensions) {
TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetRecvRtpHeaderExtensions");
- LOG(LS_INFO) << "SetRecvRtpHeaderExtensions: "
- << RtpExtensionsToString(extensions);
- if (!ValidateRtpHeaderExtensionIds(extensions))
+ if (!ValidateRtpExtensions(extensions)) {
return false;
-
- std::vector<webrtc::RtpExtension> filtered_extensions =
- FilterRtpExtensions(extensions);
- if (!RtpExtensionsHaveChanged(recv_rtp_extensions_, filtered_extensions)) {
+ }
+ std::vector<webrtc::RtpExtension> filtered_extensions = FilterRtpExtensions(
+ extensions, webrtc::RtpExtension::IsSupportedForVideo, false);
+ if (recv_rtp_extensions_ == filtered_extensions) {
LOG(LS_INFO) << "Ignoring call to SetRecvRtpHeaderExtensions because "
"header extensions haven't changed.";
return true;
}
-
- recv_rtp_extensions_ = filtered_extensions;
+ recv_rtp_extensions_.swap(filtered_extensions);
rtc::CritScope stream_lock(&stream_crit_);
for (std::map<uint32_t, WebRtcVideoReceiveStream*>::iterator it =
@@ -1539,21 +1408,17 @@ bool WebRtcVideoChannel2::SetRecvRtpHeaderExtensions(
bool WebRtcVideoChannel2::SetSendRtpHeaderExtensions(
const std::vector<RtpHeaderExtension>& extensions) {
TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetSendRtpHeaderExtensions");
- LOG(LS_INFO) << "SetSendRtpHeaderExtensions: "
- << RtpExtensionsToString(extensions);
- if (!ValidateRtpHeaderExtensionIds(extensions))
+ if (!ValidateRtpExtensions(extensions)) {
return false;
-
- std::vector<webrtc::RtpExtension> filtered_extensions =
- FilterRtpExtensions(FilterRedundantRtpExtensions(
- extensions, kBweExtensionPriorities, kBweExtensionPrioritiesLength));
- if (!RtpExtensionsHaveChanged(send_rtp_extensions_, filtered_extensions)) {
- LOG(LS_INFO) << "Ignoring call to SetSendRtpHeaderExtensions because "
+ }
+ std::vector<webrtc::RtpExtension> filtered_extensions = FilterRtpExtensions(
+ extensions, webrtc::RtpExtension::IsSupportedForVideo, true);
+ if (send_rtp_extensions_ == filtered_extensions) {
+ LOG(LS_INFO) << "Ignoring call to SetRecvRtpHeaderExtensions because "
"header extensions haven't changed.";
return true;
}
-
- send_rtp_extensions_ = filtered_extensions;
+ send_rtp_extensions_.swap(filtered_extensions);
const webrtc::RtpExtension* cvo_extension = FindHeaderExtension(
send_rtp_extensions_, kRtpVideoRotationHeaderExtension);
@@ -1612,11 +1477,11 @@ bool WebRtcVideoChannel2::SetOptions(const VideoOptions& options) {
}
{
rtc::CritScope lock(&capturer_crit_);
- options_.cpu_overuse_detection.Get(&signal_cpu_adaptation_);
+ if (options_.cpu_overuse_detection)
+ signal_cpu_adaptation_ = *options_.cpu_overuse_detection;
}
- rtc::DiffServCodePoint dscp = options_.dscp.GetWithDefaultIfUnset(false)
- ? rtc::DSCP_AF41
- : rtc::DSCP_DEFAULT;
+ rtc::DiffServCodePoint dscp =
+ options_.dscp.value_or(false) ? rtc::DSCP_AF41 : rtc::DSCP_DEFAULT;
MediaChannel::SetDscp(dscp);
rtc::CritScope stream_lock(&stream_crit_);
for (std::map<uint32_t, WebRtcVideoSendStream*>::iterator it =
@@ -1708,12 +1573,11 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::VideoSendStreamParameters::
const webrtc::VideoSendStream::Config& config,
const VideoOptions& options,
int max_bitrate_bps,
- const Settable<VideoCodecSettings>& codec_settings)
+ const rtc::Optional<VideoCodecSettings>& codec_settings)
: config(config),
options(options),
max_bitrate_bps(max_bitrate_bps),
- codec_settings(codec_settings) {
-}
+ codec_settings(codec_settings) {}
WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder::AllocatedEncoder(
webrtc::VideoEncoder* encoder,
@@ -1737,8 +1601,11 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream(
WebRtcVideoEncoderFactory* external_encoder_factory,
const VideoOptions& options,
int max_bitrate_bps,
- const Settable<VideoCodecSettings>& codec_settings,
- const std::vector<webrtc::RtpExtension>& rtp_extensions)
+ const rtc::Optional<VideoCodecSettings>& codec_settings,
+ const std::vector<webrtc::RtpExtension>& rtp_extensions,
+ // TODO(deadbeef): Don't duplicate information between send_params,
+ // rtp_extensions, options, etc.
+ const VideoSendParameters& send_params)
: ssrcs_(sp.ssrcs),
ssrc_groups_(sp.ssrc_groups),
call_(call),
@@ -1759,10 +1626,12 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream(
&parameters_.config.rtp.rtx.ssrcs);
parameters_.config.rtp.c_name = sp.cname;
parameters_.config.rtp.extensions = rtp_extensions;
+ parameters_.config.rtp.rtcp_mode = send_params.rtcp.reduced_size
+ ? webrtc::RtcpMode::kReducedSize
+ : webrtc::RtcpMode::kCompound;
- VideoCodecSettings params;
- if (codec_settings.Get(&params)) {
- SetCodec(params);
+ if (codec_settings) {
+ SetCodec(*codec_settings);
}
}
@@ -1940,11 +1809,10 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetApplyRotation(
void WebRtcVideoChannel2::WebRtcVideoSendStream::SetOptions(
const VideoOptions& options) {
rtc::CritScope cs(&lock_);
- VideoCodecSettings codec_settings;
- if (parameters_.codec_settings.Get(&codec_settings)) {
+ if (parameters_.codec_settings) {
LOG(LS_INFO) << "SetCodecAndOptions because of SetOptions; options="
<< options.ToString();
- SetCodecAndOptions(codec_settings, options);
+ SetCodecAndOptions(*parameters_.codec_settings, options);
} else {
parameters_.options = options;
}
@@ -2049,10 +1917,12 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodecAndOptions(
parameters_.config.rtp.nack.rtp_history_ms =
HasNack(codec_settings.codec) ? kNackHistoryMs : 0;
- options.suspend_below_min_bitrate.Get(
- &parameters_.config.suspend_below_min_bitrate);
+ RTC_CHECK(options.suspend_below_min_bitrate);
+ parameters_.config.suspend_below_min_bitrate =
+ *options.suspend_below_min_bitrate;
- parameters_.codec_settings.Set(codec_settings);
+ parameters_.codec_settings =
+ rtc::Optional<WebRtcVideoChannel2::VideoCodecSettings>(codec_settings);
parameters_.options = options;
LOG(LS_INFO)
@@ -2075,17 +1945,27 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpExtensions(
}
}
+void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSendParameters(
+ const VideoSendParameters& send_params) {
+ rtc::CritScope cs(&lock_);
+ parameters_.config.rtp.rtcp_mode = send_params.rtcp.reduced_size
+ ? webrtc::RtcpMode::kReducedSize
+ : webrtc::RtcpMode::kCompound;
+ if (stream_ != nullptr) {
+ LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetSendParameters";
+ RecreateWebRtcStream();
+ }
+}
+
webrtc::VideoEncoderConfig
WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoderConfig(
const Dimensions& dimensions,
const VideoCodec& codec) const {
webrtc::VideoEncoderConfig encoder_config;
if (dimensions.is_screencast) {
- int screencast_min_bitrate_kbps;
- parameters_.options.screencast_min_bitrate.Get(
- &screencast_min_bitrate_kbps);
+ RTC_CHECK(parameters_.options.screencast_min_bitrate);
encoder_config.min_transmit_bitrate_bps =
- screencast_min_bitrate_kbps * 1000;
+ *parameters_.options.screencast_min_bitrate * 1000;
encoder_config.content_type =
webrtc::VideoEncoderConfig::ContentType::kScreen;
} else {
@@ -2121,7 +2001,7 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoderConfig(
parameters_.max_bitrate_bps, stream_count);
// Conference mode screencast uses 2 temporal layers split at 100kbit.
- if (parameters_.options.conference_mode.GetWithDefaultIfUnset(false) &&
+ if (parameters_.options.conference_mode.value_or(false) &&
dimensions.is_screencast && encoder_config.streams.size() == 1) {
ScreenshareLayerConfig config = ScreenshareLayerConfig::GetDefault();
@@ -2156,8 +2036,8 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions(
RTC_DCHECK(!parameters_.encoder_config.streams.empty());
- VideoCodecSettings codec_settings;
- parameters_.codec_settings.Get(&codec_settings);
+ RTC_CHECK(parameters_.codec_settings);
+ VideoCodecSettings codec_settings = *parameters_.codec_settings;
webrtc::VideoEncoderConfig encoder_config =
CreateVideoEncoderConfig(last_dimensions_, codec_settings.codec);
@@ -2202,9 +2082,8 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() {
for (uint32_t ssrc : parameters_.config.rtp.ssrcs)
info.add_ssrc(ssrc);
- VideoCodecSettings codec_settings;
- if (parameters_.codec_settings.Get(&codec_settings))
- info.codec_name = codec_settings.codec.name;
+ if (parameters_.codec_settings)
+ info.codec_name = parameters_.codec_settings->codec.name;
for (size_t i = 0; i < parameters_.encoder_config.streams.size(); ++i) {
if (i == parameters_.encoder_config.streams.size() - 1) {
info.preferred_bitrate +=
@@ -2238,6 +2117,15 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() {
}
}
}
+
+ // Get bandwidth limitation info from stream_->GetStats().
+ // Input resolution (output from video_adapter) can be further scaled down or
+ // higher video layer(s) can be dropped due to bitrate constraints.
+ // Note, adapt_changes only include changes from the video_adapter.
+ if (stats.bw_limited_resolution)
+ info.adapt_reason |= CoordinatedVideoAdapter::ADAPTREASON_BANDWIDTH;
+
+ info.encoder_implementation_name = stats.encoder_implementation_name;
info.ssrc_groups = ssrc_groups_;
info.framerate_input = stats.input_frame_rate;
info.framerate_sent = stats.encode_frame_rate;
@@ -2316,11 +2204,10 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() {
call_->DestroyVideoSendStream(stream_);
}
- VideoCodecSettings codec_settings;
- parameters_.codec_settings.Get(&codec_settings);
+ RTC_CHECK(parameters_.codec_settings);
parameters_.encoder_config.encoder_specific_settings =
ConfigureVideoEncoderSettings(
- codec_settings.codec, parameters_.options,
+ parameters_.codec_settings->codec, parameters_.options,
parameters_.encoder_config.content_type ==
webrtc::VideoEncoderConfig::ContentType::kScreen);
@@ -2345,7 +2232,8 @@ WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream(
const webrtc::VideoReceiveStream::Config& config,
WebRtcVideoDecoderFactory* external_decoder_factory,
bool default_stream,
- const std::vector<VideoCodecSettings>& recv_codecs)
+ const std::vector<VideoCodecSettings>& recv_codecs,
+ bool disable_prerenderer_smoothing)
: call_(call),
ssrcs_(sp.ssrcs),
ssrc_groups_(sp.ssrc_groups),
@@ -2353,6 +2241,7 @@ WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream(
default_stream_(default_stream),
config_(config),
external_decoder_factory_(external_decoder_factory),
+ disable_prerenderer_smoothing_(disable_prerenderer_smoothing),
renderer_(NULL),
last_width_(-1),
last_height_(-1),
@@ -2457,10 +2346,10 @@ void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRecvCodecs(
config_.rtp.nack.rtp_history_ms =
HasNack(recv_codecs.begin()->codec) ? kNackHistoryMs : 0;
- ClearDecoders(&old_decoders);
LOG(LS_INFO) << "RecreateWebRtcStream (recv) because of SetRecvCodecs: "
<< CodecSettingsVectorToString(recv_codecs);
RecreateWebRtcStream();
+ ClearDecoders(&old_decoders);
}
void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetLocalSsrc(
@@ -2482,20 +2371,28 @@ void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetLocalSsrc(
RecreateWebRtcStream();
}
-void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetNackAndRemb(
- bool nack_enabled, bool remb_enabled) {
+void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetFeedbackParameters(
+ bool nack_enabled,
+ bool remb_enabled,
+ bool transport_cc_enabled) {
int nack_history_ms = nack_enabled ? kNackHistoryMs : 0;
if (config_.rtp.nack.rtp_history_ms == nack_history_ms &&
- config_.rtp.remb == remb_enabled) {
- LOG(LS_INFO) << "Ignoring call to SetNackAndRemb because parameters are "
- "unchanged; nack=" << nack_enabled
- << ", remb=" << remb_enabled;
+ config_.rtp.remb == remb_enabled &&
+ config_.rtp.transport_cc == transport_cc_enabled) {
+ LOG(LS_INFO)
+ << "Ignoring call to SetFeedbackParameters because parameters are "
+ "unchanged; nack="
+ << nack_enabled << ", remb=" << remb_enabled
+ << ", transport_cc=" << transport_cc_enabled;
return;
}
config_.rtp.remb = remb_enabled;
config_.rtp.nack.rtp_history_ms = nack_history_ms;
- LOG(LS_INFO) << "RecreateWebRtcStream (recv) because of SetNackAndRemb; nack="
- << nack_enabled << ", remb=" << remb_enabled;
+ config_.rtp.transport_cc = transport_cc_enabled;
+ LOG(LS_INFO)
+ << "RecreateWebRtcStream (recv) because of SetFeedbackParameters; nack="
+ << nack_enabled << ", remb=" << remb_enabled
+ << ", transport_cc=" << transport_cc_enabled;
RecreateWebRtcStream();
}
@@ -2506,6 +2403,15 @@ void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRtpExtensions(
RecreateWebRtcStream();
}
+void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRecvParameters(
+ const VideoRecvParameters& recv_params) {
+ config_.rtp.rtcp_mode = recv_params.rtcp.reduced_size
+ ? webrtc::RtcpMode::kReducedSize
+ : webrtc::RtcpMode::kCompound;
+ LOG(LS_INFO) << "RecreateWebRtcStream (recv) because of SetRecvParameters";
+ RecreateWebRtcStream();
+}
+
void WebRtcVideoChannel2::WebRtcVideoReceiveStream::RecreateWebRtcStream() {
if (stream_ != NULL) {
call_->DestroyVideoReceiveStream(stream_);
@@ -2560,6 +2466,11 @@ bool WebRtcVideoChannel2::WebRtcVideoReceiveStream::IsTextureSupported() const {
return true;
}
+bool WebRtcVideoChannel2::WebRtcVideoReceiveStream::SmoothsRenderedFrames()
+ const {
+ return disable_prerenderer_smoothing_;
+}
+
bool WebRtcVideoChannel2::WebRtcVideoReceiveStream::IsDefaultStream() const {
return default_stream_;
}
@@ -2607,6 +2518,7 @@ WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetVideoReceiverInfo() {
info.ssrc_groups = ssrc_groups_;
info.add_ssrc(config_.rtp.remote_ssrc);
webrtc::VideoReceiveStream::Stats stats = stream_->GetStats();
+ info.decoder_implementation_name = stats.decoder_implementation_name;
info.bytes_rcvd = stats.rtp_stats.transmitted.payload_bytes +
stats.rtp_stats.transmitted.header_bytes +
stats.rtp_stats.transmitted.padding_bytes;
diff --git a/talk/media/webrtc/webrtcvideoengine2.h b/talk/media/webrtc/webrtcvideoengine2.h
index 7096135cdd..1b8da16368 100644
--- a/talk/media/webrtc/webrtcvideoengine2.h
+++ b/talk/media/webrtc/webrtcvideoengine2.h
@@ -112,14 +112,11 @@ class WebRtcVideoEngine2 {
// Basic video engine implementation.
void Init();
- bool SetDefaultEncoderConfig(const VideoEncoderConfig& config);
-
WebRtcVideoChannel2* CreateChannel(webrtc::Call* call,
const VideoOptions& options);
const std::vector<VideoCodec>& codecs() const;
- const std::vector<RtpHeaderExtension>& rtp_header_extensions() const;
- void SetLogging(int min_sev, const char* filter);
+ RtpCapabilities GetCapabilities() const;
// Set a WebRtcVideoDecoderFactory for external decoding. Video engine does
// not take the ownership of |decoder_factory|. The caller needs to make sure
@@ -134,9 +131,6 @@ class WebRtcVideoEngine2 {
bool EnableTimedRender();
bool FindCodec(const VideoCodec& in);
- bool CanSendCodec(const VideoCodec& in,
- const VideoCodec& current,
- VideoCodec* out);
// Check whether the supplied trace should be ignored.
bool ShouldIgnoreTrace(const std::string& trace);
@@ -144,7 +138,6 @@ class WebRtcVideoEngine2 {
std::vector<VideoCodec> GetSupportedCodecs() const;
std::vector<VideoCodec> video_codecs_;
- std::vector<RtpHeaderExtension> rtp_header_extensions_;
bool initialized_;
@@ -250,14 +243,18 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler,
WebRtcVideoEncoderFactory* external_encoder_factory,
const VideoOptions& options,
int max_bitrate_bps,
- const Settable<VideoCodecSettings>& codec_settings,
- const std::vector<webrtc::RtpExtension>& rtp_extensions);
+ const rtc::Optional<VideoCodecSettings>& codec_settings,
+ const std::vector<webrtc::RtpExtension>& rtp_extensions,
+ const VideoSendParameters& send_params);
~WebRtcVideoSendStream();
void SetOptions(const VideoOptions& options);
void SetCodec(const VideoCodecSettings& codec);
void SetRtpExtensions(
const std::vector<webrtc::RtpExtension>& rtp_extensions);
+ // TODO(deadbeef): Move logic from SetCodec/SetRtpExtensions/etc.
+ // into this method. Currently this method only sets the RTCP mode.
+ void SetSendParameters(const VideoSendParameters& send_params);
void InputFrame(VideoCapturer* capturer, const VideoFrame* frame);
bool SetCapturer(VideoCapturer* capturer);
@@ -286,11 +283,11 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler,
const webrtc::VideoSendStream::Config& config,
const VideoOptions& options,
int max_bitrate_bps,
- const Settable<VideoCodecSettings>& codec_settings);
+ const rtc::Optional<VideoCodecSettings>& codec_settings);
webrtc::VideoSendStream::Config config;
VideoOptions options;
int max_bitrate_bps;
- Settable<VideoCodecSettings> codec_settings;
+ rtc::Optional<VideoCodecSettings> codec_settings;
// Sent resolutions + bitrates etc. by the underlying VideoSendStream,
// typically changes when setting a new resolution or reconfiguring
// bitrates.
@@ -395,19 +392,26 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler,
const webrtc::VideoReceiveStream::Config& config,
WebRtcVideoDecoderFactory* external_decoder_factory,
bool default_stream,
- const std::vector<VideoCodecSettings>& recv_codecs);
+ const std::vector<VideoCodecSettings>& recv_codecs,
+ bool disable_prerenderer_smoothing);
~WebRtcVideoReceiveStream();
const std::vector<uint32_t>& GetSsrcs() const;
void SetLocalSsrc(uint32_t local_ssrc);
- void SetNackAndRemb(bool nack_enabled, bool remb_enabled);
+ void SetFeedbackParameters(bool nack_enabled,
+ bool remb_enabled,
+ bool transport_cc_enabled);
void SetRecvCodecs(const std::vector<VideoCodecSettings>& recv_codecs);
void SetRtpExtensions(const std::vector<webrtc::RtpExtension>& extensions);
+ // TODO(deadbeef): Move logic from SetRecvCodecs/SetRtpExtensions/etc.
+ // into this method. Currently this method only sets the RTCP mode.
+ void SetRecvParameters(const VideoRecvParameters& recv_params);
void RenderFrame(const webrtc::VideoFrame& frame,
int time_to_render_ms) override;
bool IsTextureSupported() const override;
+ bool SmoothsRenderedFrames() const override;
bool IsDefaultStream() const;
void SetRenderer(cricket::VideoRenderer* renderer);
@@ -448,6 +452,8 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler,
WebRtcVideoDecoderFactory* const external_decoder_factory_;
std::vector<AllocatedDecoder> allocated_decoders_;
+ const bool disable_prerenderer_smoothing_;
+
rtc::CriticalSection renderer_lock_;
cricket::VideoRenderer* renderer_ GUARDED_BY(renderer_lock_);
int last_width_ GUARDED_BY(renderer_lock_);
@@ -512,7 +518,7 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler,
std::set<uint32_t> send_ssrcs_ GUARDED_BY(stream_crit_);
std::set<uint32_t> receive_ssrcs_ GUARDED_BY(stream_crit_);
- Settable<VideoCodecSettings> send_codec_;
+ rtc::Optional<VideoCodecSettings> send_codec_;
std::vector<webrtc::RtpExtension> send_rtp_extensions_;
WebRtcVideoEncoderFactory* const external_encoder_factory_;
@@ -521,6 +527,10 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler,
std::vector<webrtc::RtpExtension> recv_rtp_extensions_;
webrtc::Call::Config::BitrateConfig bitrate_config_;
VideoOptions options_;
+ // TODO(deadbeef): Don't duplicate information between
+ // send_params/recv_params, rtp_extensions, options, etc.
+ VideoSendParameters send_params_;
+ VideoRecvParameters recv_params_;
};
} // namespace cricket
diff --git a/talk/media/webrtc/webrtcvideoengine2_unittest.cc b/talk/media/webrtc/webrtcvideoengine2_unittest.cc
index c0cd2ffa50..41e04a9fa7 100644
--- a/talk/media/webrtc/webrtcvideoengine2_unittest.cc
+++ b/talk/media/webrtc/webrtcvideoengine2_unittest.cc
@@ -75,6 +75,8 @@ void VerifyCodecHasDefaultFeedbackParams(const cricket::VideoCodec& codec) {
EXPECT_TRUE(codec.HasFeedbackParam(cricket::FeedbackParam(
cricket::kRtcpFbParamRemb, cricket::kParamValueEmpty)));
EXPECT_TRUE(codec.HasFeedbackParam(cricket::FeedbackParam(
+ cricket::kRtcpFbParamTransportCc, cricket::kParamValueEmpty)));
+ EXPECT_TRUE(codec.HasFeedbackParam(cricket::FeedbackParam(
cricket::kRtcpFbParamCcm, cricket::kRtcpFbCcmParamFir)));
}
@@ -205,26 +207,6 @@ TEST_F(WebRtcVideoEngine2Test, FindCodec) {
EXPECT_TRUE(engine_.FindCodec(rtx));
}
-TEST_F(WebRtcVideoEngine2Test, SetDefaultEncoderConfigPreservesFeedbackParams) {
- cricket::VideoCodec max_settings(
- engine_.codecs()[0].id, engine_.codecs()[0].name,
- engine_.codecs()[0].width / 2, engine_.codecs()[0].height / 2, 30, 0);
- // This codec shouldn't have NACK by default or the test is pointless.
- EXPECT_FALSE(max_settings.HasFeedbackParam(
- FeedbackParam(kRtcpFbParamNack, kParamValueEmpty)));
- // The engine should by default have it however.
- EXPECT_TRUE(engine_.codecs()[0].HasFeedbackParam(
- FeedbackParam(kRtcpFbParamNack, kParamValueEmpty)));
-
- // Set constrained max codec settings.
- EXPECT_TRUE(engine_.SetDefaultEncoderConfig(
- cricket::VideoEncoderConfig(max_settings)));
-
- // Verify that feedback parameters are retained.
- EXPECT_TRUE(engine_.codecs()[0].HasFeedbackParam(
- FeedbackParam(kRtcpFbParamNack, kParamValueEmpty)));
-}
-
TEST_F(WebRtcVideoEngine2Test, DefaultRtxCodecHasAssociatedPayloadTypeSet) {
std::vector<VideoCodec> engine_codecs = engine_.codecs();
for (size_t i = 0; i < engine_codecs.size(); ++i) {
@@ -240,11 +222,11 @@ TEST_F(WebRtcVideoEngine2Test, DefaultRtxCodecHasAssociatedPayloadTypeSet) {
}
TEST_F(WebRtcVideoEngine2Test, SupportsTimestampOffsetHeaderExtension) {
- std::vector<RtpHeaderExtension> extensions = engine_.rtp_header_extensions();
- ASSERT_FALSE(extensions.empty());
- for (size_t i = 0; i < extensions.size(); ++i) {
- if (extensions[i].uri == kRtpTimestampOffsetHeaderExtension) {
- EXPECT_EQ(kRtpTimestampOffsetHeaderExtensionDefaultId, extensions[i].id);
+ RtpCapabilities capabilities = engine_.GetCapabilities();
+ ASSERT_FALSE(capabilities.header_extensions.empty());
+ for (const RtpHeaderExtension& extension : capabilities.header_extensions) {
+ if (extension.uri == kRtpTimestampOffsetHeaderExtension) {
+ EXPECT_EQ(kRtpTimestampOffsetHeaderExtensionDefaultId, extension.id);
return;
}
}
@@ -252,12 +234,11 @@ TEST_F(WebRtcVideoEngine2Test, SupportsTimestampOffsetHeaderExtension) {
}
TEST_F(WebRtcVideoEngine2Test, SupportsAbsoluteSenderTimeHeaderExtension) {
- std::vector<RtpHeaderExtension> extensions = engine_.rtp_header_extensions();
- ASSERT_FALSE(extensions.empty());
- for (size_t i = 0; i < extensions.size(); ++i) {
- if (extensions[i].uri == kRtpAbsoluteSenderTimeHeaderExtension) {
- EXPECT_EQ(kRtpAbsoluteSenderTimeHeaderExtensionDefaultId,
- extensions[i].id);
+ RtpCapabilities capabilities = engine_.GetCapabilities();
+ ASSERT_FALSE(capabilities.header_extensions.empty());
+ for (const RtpHeaderExtension& extension : capabilities.header_extensions) {
+ if (extension.uri == kRtpAbsoluteSenderTimeHeaderExtension) {
+ EXPECT_EQ(kRtpAbsoluteSenderTimeHeaderExtensionDefaultId, extension.id);
return;
}
}
@@ -272,12 +253,12 @@ class WebRtcVideoEngine2WithSendSideBweTest : public WebRtcVideoEngine2Test {
TEST_F(WebRtcVideoEngine2WithSendSideBweTest,
SupportsTransportSequenceNumberHeaderExtension) {
- std::vector<RtpHeaderExtension> extensions = engine_.rtp_header_extensions();
- ASSERT_FALSE(extensions.empty());
- for (size_t i = 0; i < extensions.size(); ++i) {
- if (extensions[i].uri == kRtpTransportSequenceNumberHeaderExtension) {
+ RtpCapabilities capabilities = engine_.GetCapabilities();
+ ASSERT_FALSE(capabilities.header_extensions.empty());
+ for (const RtpHeaderExtension& extension : capabilities.header_extensions) {
+ if (extension.uri == kRtpTransportSequenceNumberHeaderExtension) {
EXPECT_EQ(kRtpTransportSequenceNumberHeaderExtensionDefaultId,
- extensions[i].id);
+ extension.id);
return;
}
}
@@ -285,11 +266,11 @@ TEST_F(WebRtcVideoEngine2WithSendSideBweTest,
}
TEST_F(WebRtcVideoEngine2Test, SupportsVideoRotationHeaderExtension) {
- std::vector<RtpHeaderExtension> extensions = engine_.rtp_header_extensions();
- ASSERT_FALSE(extensions.empty());
- for (size_t i = 0; i < extensions.size(); ++i) {
- if (extensions[i].uri == kRtpVideoRotationHeaderExtension) {
- EXPECT_EQ(kRtpVideoRotationHeaderExtensionDefaultId, extensions[i].id);
+ RtpCapabilities capabilities = engine_.GetCapabilities();
+ ASSERT_FALSE(capabilities.header_extensions.empty());
+ for (const RtpHeaderExtension& extension : capabilities.header_extensions) {
+ if (extension.uri == kRtpVideoRotationHeaderExtension) {
+ EXPECT_EQ(kRtpVideoRotationHeaderExtensionDefaultId, extension.id);
return;
}
}
@@ -794,17 +775,6 @@ TEST_F(WebRtcVideoEngine2Test, RegisterExternalH264DecoderIfSupported) {
ASSERT_EQ(1u, decoder_factory.decoders().size());
}
-class WebRtcVideoEngine2BaseTest
- : public VideoEngineTest<cricket::WebRtcVideoEngine2> {
- protected:
- typedef VideoEngineTest<cricket::WebRtcVideoEngine2> Base;
-};
-
-#define WEBRTC_ENGINE_BASE_TEST(test) \
- TEST_F(WebRtcVideoEngine2BaseTest, test) { Base::test##Body(); }
-
-WEBRTC_ENGINE_BASE_TEST(ConstrainNewCodec2);
-
class WebRtcVideoChannel2BaseTest
: public VideoMediaChannelTest<WebRtcVideoEngine2, WebRtcVideoChannel2> {
protected:
@@ -894,7 +864,10 @@ TEST_F(WebRtcVideoChannel2BaseTest, TwoStreamsReUseFirstStream) {
Base::TwoStreamsReUseFirstStream(kVp8Codec);
}
+//Disabled for TSan: https://bugs.chromium.org/p/webrtc/issues/detail?id=4963
+#if !defined(THREAD_SANITIZER)
WEBRTC_BASE_TEST(SendManyResizeOnce);
+#endif // THREAD_SANITIZER
// TODO(pbos): Enable and figure out why this fails (or should work).
TEST_F(WebRtcVideoChannel2BaseTest, DISABLED_SendVp8HdAndReceiveAdaptedVp8Vga) {
@@ -1097,7 +1070,7 @@ class WebRtcVideoChannel2Test : public WebRtcVideoEngine2Test {
FakeVideoSendStream* SetDenoisingOption(
const cricket::VideoSendParameters& parameters, bool enabled) {
cricket::VideoSendParameters params = parameters;
- params.options.video_noise_reduction.Set(enabled);
+ params.options.video_noise_reduction = rtc::Optional<bool>(enabled);
channel_->SetSendParameters(params);
return fake_call_->GetVideoSendStreams().back();
}
@@ -1148,7 +1121,7 @@ TEST_F(WebRtcVideoChannel2Test, RecvStreamWithSimAndRtx) {
parameters.codecs = engine_.codecs();
EXPECT_TRUE(channel_->SetSendParameters(parameters));
EXPECT_TRUE(channel_->SetSend(true));
- parameters.options.conference_mode.Set(true);
+ parameters.options.conference_mode = rtc::Optional<bool>(true);
EXPECT_TRUE(channel_->SetSendParameters(parameters));
// Send side.
@@ -1451,6 +1424,11 @@ TEST_F(WebRtcVideoChannel2Test, RembIsEnabledByDefault) {
EXPECT_TRUE(stream->GetConfig().rtp.remb);
}
+TEST_F(WebRtcVideoChannel2Test, TransportCcIsEnabledByDefault) {
+ FakeVideoReceiveStream* stream = AddRecvStream();
+ EXPECT_TRUE(stream->GetConfig().rtp.transport_cc);
+}
+
TEST_F(WebRtcVideoChannel2Test, RembCanBeEnabledAndDisabled) {
FakeVideoReceiveStream* stream = AddRecvStream();
EXPECT_TRUE(stream->GetConfig().rtp.remb);
@@ -1471,6 +1449,27 @@ TEST_F(WebRtcVideoChannel2Test, RembCanBeEnabledAndDisabled) {
EXPECT_TRUE(stream->GetConfig().rtp.remb);
}
+TEST_F(WebRtcVideoChannel2Test, TransportCcCanBeEnabledAndDisabled) {
+ FakeVideoReceiveStream* stream = AddRecvStream();
+ EXPECT_TRUE(stream->GetConfig().rtp.transport_cc);
+
+ // Verify that transport cc feedback is turned off when send(!) codecs without
+ // transport cc feedback are set.
+ cricket::VideoSendParameters parameters;
+ parameters.codecs.push_back(kVp8Codec);
+ EXPECT_TRUE(parameters.codecs[0].feedback_params.params().empty());
+ EXPECT_TRUE(channel_->SetSendParameters(parameters));
+ stream = fake_call_->GetVideoReceiveStreams()[0];
+ EXPECT_FALSE(stream->GetConfig().rtp.transport_cc);
+
+ // Verify that transport cc feedback is turned on when setting default codecs
+ // since the default codecs have transport cc feedback enabled.
+ parameters.codecs = engine_.codecs();
+ EXPECT_TRUE(channel_->SetSendParameters(parameters));
+ stream = fake_call_->GetVideoReceiveStreams()[0];
+ EXPECT_TRUE(stream->GetConfig().rtp.transport_cc);
+}
+
TEST_F(WebRtcVideoChannel2Test, NackIsEnabledByDefault) {
VerifyCodecHasDefaultFeedbackParams(default_codec_);
@@ -1558,7 +1557,8 @@ TEST_F(WebRtcVideoChannel2Test, UsesCorrectSettingsForScreencast) {
cricket::VideoCodec codec = kVp8Codec360p;
cricket::VideoSendParameters parameters;
parameters.codecs.push_back(codec);
- parameters.options.screencast_min_bitrate.Set(kScreenshareMinBitrateKbps);
+ parameters.options.screencast_min_bitrate =
+ rtc::Optional<int>(kScreenshareMinBitrateKbps);
EXPECT_TRUE(channel_->SetSendParameters(parameters));
AddSendStream();
@@ -1612,7 +1612,7 @@ TEST_F(WebRtcVideoChannel2Test,
ConferenceModeScreencastConfiguresTemporalLayer) {
static const int kConferenceScreencastTemporalBitrateBps =
ScreenshareLayerConfig::GetDefault().tl0_bitrate_kbps * 1000;
- send_parameters_.options.conference_mode.Set(true);
+ send_parameters_.options.conference_mode = rtc::Optional<bool>(true);
channel_->SetSendParameters(send_parameters_);
AddSendStream();
@@ -1659,13 +1659,15 @@ TEST_F(WebRtcVideoChannel2Test, SuspendBelowMinBitrateDisabledByDefault) {
}
TEST_F(WebRtcVideoChannel2Test, SetOptionsWithSuspendBelowMinBitrate) {
- send_parameters_.options.suspend_below_min_bitrate.Set(true);
+ send_parameters_.options.suspend_below_min_bitrate =
+ rtc::Optional<bool>(true);
channel_->SetSendParameters(send_parameters_);
FakeVideoSendStream* stream = AddSendStream();
EXPECT_TRUE(stream->GetConfig().suspend_below_min_bitrate);
- send_parameters_.options.suspend_below_min_bitrate.Set(false);
+ send_parameters_.options.suspend_below_min_bitrate =
+ rtc::Optional<bool>(false);
channel_->SetSendParameters(send_parameters_);
stream = fake_call_->GetVideoSendStreams()[0];
@@ -1853,7 +1855,7 @@ void WebRtcVideoChannel2Test::TestCpuAdaptation(bool enable_overuse,
cricket::VideoSendParameters parameters;
parameters.codecs.push_back(codec);
if (!enable_overuse) {
- parameters.options.cpu_overuse_detection.Set(false);
+ parameters.options.cpu_overuse_detection = rtc::Optional<bool>(false);
}
EXPECT_TRUE(channel_->SetSendParameters(parameters));
@@ -2375,19 +2377,55 @@ TEST_F(WebRtcVideoChannel2Test, TestSetDscpOptions) {
cricket::VideoSendParameters parameters = send_parameters_;
EXPECT_TRUE(channel_->SetSendParameters(parameters));
EXPECT_EQ(rtc::DSCP_NO_CHANGE, network_interface->dscp());
- parameters.options.dscp.Set(true);
+ parameters.options.dscp = rtc::Optional<bool>(true);
EXPECT_TRUE(channel_->SetSendParameters(parameters));
EXPECT_EQ(rtc::DSCP_AF41, network_interface->dscp());
// Verify previous value is not modified if dscp option is not set.
cricket::VideoSendParameters parameters1 = send_parameters_;
EXPECT_TRUE(channel_->SetSendParameters(parameters1));
EXPECT_EQ(rtc::DSCP_AF41, network_interface->dscp());
- parameters1.options.dscp.Set(false);
+ parameters1.options.dscp = rtc::Optional<bool>(false);
EXPECT_TRUE(channel_->SetSendParameters(parameters1));
EXPECT_EQ(rtc::DSCP_DEFAULT, network_interface->dscp());
channel_->SetInterface(NULL);
}
+// This test verifies that the RTCP reduced size mode is properly applied to
+// send video streams.
+TEST_F(WebRtcVideoChannel2Test, TestSetSendRtcpReducedSize) {
+ // Create stream, expecting that default mode is "compound".
+ FakeVideoSendStream* stream1 = AddSendStream();
+ EXPECT_EQ(webrtc::RtcpMode::kCompound, stream1->GetConfig().rtp.rtcp_mode);
+
+ // Now enable reduced size mode.
+ send_parameters_.rtcp.reduced_size = true;
+ EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
+ stream1 = fake_call_->GetVideoSendStreams()[0];
+ EXPECT_EQ(webrtc::RtcpMode::kReducedSize, stream1->GetConfig().rtp.rtcp_mode);
+
+ // Create a new stream and ensure it picks up the reduced size mode.
+ FakeVideoSendStream* stream2 = AddSendStream();
+ EXPECT_EQ(webrtc::RtcpMode::kReducedSize, stream2->GetConfig().rtp.rtcp_mode);
+}
+
+// This test verifies that the RTCP reduced size mode is properly applied to
+// receive video streams.
+TEST_F(WebRtcVideoChannel2Test, TestSetRecvRtcpReducedSize) {
+ // Create stream, expecting that default mode is "compound".
+ FakeVideoReceiveStream* stream1 = AddRecvStream();
+ EXPECT_EQ(webrtc::RtcpMode::kCompound, stream1->GetConfig().rtp.rtcp_mode);
+
+ // Now enable reduced size mode.
+ recv_parameters_.rtcp.reduced_size = true;
+ EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
+ stream1 = fake_call_->GetVideoReceiveStreams()[0];
+ EXPECT_EQ(webrtc::RtcpMode::kReducedSize, stream1->GetConfig().rtp.rtcp_mode);
+
+ // Create a new stream and ensure it picks up the reduced size mode.
+ FakeVideoReceiveStream* stream2 = AddRecvStream();
+ EXPECT_EQ(webrtc::RtcpMode::kReducedSize, stream2->GetConfig().rtp.rtcp_mode);
+}
+
TEST_F(WebRtcVideoChannel2Test, OnReadyToSendSignalsNetworkState) {
EXPECT_EQ(webrtc::kNetworkUp, fake_call_->GetNetworkState());
@@ -2410,6 +2448,18 @@ TEST_F(WebRtcVideoChannel2Test, GetStatsReportsSentCodecName) {
EXPECT_EQ(kVp8Codec.name, info.senders[0].codec_name);
}
+TEST_F(WebRtcVideoChannel2Test, GetStatsReportsEncoderImplementationName) {
+ FakeVideoSendStream* stream = AddSendStream();
+ webrtc::VideoSendStream::Stats stats;
+ stats.encoder_implementation_name = "encoder_implementation_name";
+ stream->SetStats(stats);
+
+ cricket::VideoMediaInfo info;
+ ASSERT_TRUE(channel_->GetStats(&info));
+ EXPECT_EQ(stats.encoder_implementation_name,
+ info.senders[0].encoder_implementation_name);
+}
+
TEST_F(WebRtcVideoChannel2Test, GetStatsReportsCpuOveruseMetrics) {
FakeVideoSendStream* stream = AddSendStream();
webrtc::VideoSendStream::Stats stats;
@@ -2460,7 +2510,7 @@ TEST_F(WebRtcVideoChannel2Test, GetStatsTracksAdaptationStats) {
EXPECT_TRUE(channel_->SetSend(true));
// Verify that the CpuOveruseObserver is registered and trigger downgrade.
- parameters.options.cpu_overuse_detection.Set(true);
+ parameters.options.cpu_overuse_detection = rtc::Optional<bool>(true);
EXPECT_TRUE(channel_->SetSendParameters(parameters));
// Trigger overuse.
@@ -2518,6 +2568,87 @@ TEST_F(WebRtcVideoChannel2Test, GetStatsTracksAdaptationStats) {
EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], NULL));
}
+TEST_F(WebRtcVideoChannel2Test, GetStatsTracksAdaptationAndBandwidthStats) {
+ AddSendStream(cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs3)));
+
+ // Capture format VGA.
+ cricket::FakeVideoCapturer video_capturer_vga;
+ const std::vector<cricket::VideoFormat>* formats =
+ video_capturer_vga.GetSupportedFormats();
+ cricket::VideoFormat capture_format_vga = (*formats)[1];
+ EXPECT_EQ(cricket::CS_RUNNING, video_capturer_vga.Start(capture_format_vga));
+ EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], &video_capturer_vga));
+ EXPECT_TRUE(video_capturer_vga.CaptureFrame());
+
+ cricket::VideoCodec send_codec(100, "VP8", 640, 480, 30, 0);
+ cricket::VideoSendParameters parameters;
+ parameters.codecs.push_back(send_codec);
+ EXPECT_TRUE(channel_->SetSendParameters(parameters));
+ EXPECT_TRUE(channel_->SetSend(true));
+
+ // Verify that the CpuOveruseObserver is registered and trigger downgrade.
+ parameters.options.cpu_overuse_detection = rtc::Optional<bool>(true);
+ EXPECT_TRUE(channel_->SetSendParameters(parameters));
+
+ // Trigger overuse -> adapt CPU.
+ ASSERT_EQ(1u, fake_call_->GetVideoSendStreams().size());
+ webrtc::LoadObserver* overuse_callback =
+ fake_call_->GetVideoSendStreams().front()->GetConfig().overuse_callback;
+ ASSERT_TRUE(overuse_callback != NULL);
+ overuse_callback->OnLoadUpdate(webrtc::LoadObserver::kOveruse);
+ EXPECT_TRUE(video_capturer_vga.CaptureFrame());
+ cricket::VideoMediaInfo info;
+ EXPECT_TRUE(channel_->GetStats(&info));
+ ASSERT_EQ(1U, info.senders.size());
+ EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU,
+ info.senders[0].adapt_reason);
+
+ // Set bandwidth limitation stats for the stream -> adapt CPU + BW.
+ webrtc::VideoSendStream::Stats stats;
+ stats.bw_limited_resolution = true;
+ fake_call_->GetVideoSendStreams().front()->SetStats(stats);
+ info.Clear();
+ EXPECT_TRUE(channel_->GetStats(&info));
+ ASSERT_EQ(1U, info.senders.size());
+ EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU +
+ CoordinatedVideoAdapter::ADAPTREASON_BANDWIDTH,
+ info.senders[0].adapt_reason);
+
+ // Trigger upgrade -> adapt BW.
+ overuse_callback->OnLoadUpdate(webrtc::LoadObserver::kUnderuse);
+ EXPECT_TRUE(video_capturer_vga.CaptureFrame());
+ info.Clear();
+ EXPECT_TRUE(channel_->GetStats(&info));
+ ASSERT_EQ(1U, info.senders.size());
+ EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_BANDWIDTH,
+ info.senders[0].adapt_reason);
+
+ // Reset bandwidth limitation state -> adapt NONE.
+ stats.bw_limited_resolution = false;
+ fake_call_->GetVideoSendStreams().front()->SetStats(stats);
+ info.Clear();
+ EXPECT_TRUE(channel_->GetStats(&info));
+ ASSERT_EQ(1U, info.senders.size());
+ EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_NONE,
+ info.senders[0].adapt_reason);
+
+ EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], NULL));
+}
+
+TEST_F(WebRtcVideoChannel2Test,
+ GetStatsTranslatesBandwidthLimitedResolutionCorrectly) {
+ FakeVideoSendStream* stream = AddSendStream();
+ webrtc::VideoSendStream::Stats stats;
+ stats.bw_limited_resolution = true;
+ stream->SetStats(stats);
+
+ cricket::VideoMediaInfo info;
+ EXPECT_TRUE(channel_->GetStats(&info));
+ ASSERT_EQ(1U, info.senders.size());
+ EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_BANDWIDTH,
+ info.senders[0].adapt_reason);
+}
+
TEST_F(WebRtcVideoChannel2Test,
GetStatsTranslatesSendRtcpPacketTypesCorrectly) {
FakeVideoSendStream* stream = AddSendStream();
@@ -2561,6 +2692,7 @@ TEST_F(WebRtcVideoChannel2Test,
TEST_F(WebRtcVideoChannel2Test, GetStatsTranslatesDecodeStatsCorrectly) {
FakeVideoReceiveStream* stream = AddRecvStream();
webrtc::VideoReceiveStream::Stats stats;
+ stats.decoder_implementation_name = "decoder_implementation_name";
stats.decode_ms = 2;
stats.max_decode_ms = 3;
stats.current_delay_ms = 4;
@@ -2572,6 +2704,8 @@ TEST_F(WebRtcVideoChannel2Test, GetStatsTranslatesDecodeStatsCorrectly) {
cricket::VideoMediaInfo info;
ASSERT_TRUE(channel_->GetStats(&info));
+ EXPECT_EQ(stats.decoder_implementation_name,
+ info.receivers[0].decoder_implementation_name);
EXPECT_EQ(stats.decode_ms, info.receivers[0].decode_ms);
EXPECT_EQ(stats.max_decode_ms, info.receivers[0].max_decode_ms);
EXPECT_EQ(stats.current_delay_ms, info.receivers[0].current_delay_ms);
diff --git a/talk/media/webrtc/webrtcvideoframe.cc b/talk/media/webrtc/webrtcvideoframe.cc
index 7da7e3b7fb..fcc991c753 100644
--- a/talk/media/webrtc/webrtcvideoframe.cc
+++ b/talk/media/webrtc/webrtcvideoframe.cc
@@ -56,17 +56,6 @@ WebRtcVideoFrame::WebRtcVideoFrame(
rotation_(rotation) {
}
-WebRtcVideoFrame::WebRtcVideoFrame(
- const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& buffer,
- int64_t elapsed_time_ns,
- int64_t time_stamp_ns)
- : video_frame_buffer_(buffer),
- pixel_width_(1),
- pixel_height_(1),
- time_stamp_ns_(time_stamp_ns),
- rotation_(webrtc::kVideoRotation_0) {
-}
-
WebRtcVideoFrame::~WebRtcVideoFrame() {}
bool WebRtcVideoFrame::Init(uint32_t format,
@@ -90,13 +79,7 @@ bool WebRtcVideoFrame::Init(const CapturedFrame* frame, int dw, int dh,
return Reset(frame->fourcc, frame->width, frame->height, dw, dh,
static_cast<uint8_t*>(frame->data), frame->data_size,
frame->pixel_width, frame->pixel_height, frame->time_stamp,
- frame->GetRotation(), apply_rotation);
-}
-
-bool WebRtcVideoFrame::InitToBlack(int w, int h, size_t pixel_width,
- size_t pixel_height, int64_t,
- int64_t time_stamp_ns) {
- return InitToBlack(w, h, pixel_width, pixel_height, time_stamp_ns);
+ frame->rotation, apply_rotation);
}
bool WebRtcVideoFrame::InitToBlack(int w, int h, size_t pixel_width,
diff --git a/talk/media/webrtc/webrtcvideoframe.h b/talk/media/webrtc/webrtcvideoframe.h
index 0928c59324..827cf28821 100644
--- a/talk/media/webrtc/webrtcvideoframe.h
+++ b/talk/media/webrtc/webrtcvideoframe.h
@@ -33,7 +33,7 @@
#include "webrtc/base/refcount.h"
#include "webrtc/base/scoped_ref_ptr.h"
#include "webrtc/common_types.h"
-#include "webrtc/common_video/interface/video_frame_buffer.h"
+#include "webrtc/common_video/include/video_frame_buffer.h"
namespace cricket {
@@ -46,11 +46,6 @@ class WebRtcVideoFrame : public VideoFrame {
int64_t time_stamp_ns,
webrtc::VideoRotation rotation);
- // TODO(guoweis): Remove this when chrome code base is updated.
- WebRtcVideoFrame(const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& buffer,
- int64_t elapsed_time_ns,
- int64_t time_stamp_ns);
-
~WebRtcVideoFrame();
// Creates a frame from a raw sample with FourCC "format" and size "w" x "h".
@@ -74,10 +69,6 @@ class WebRtcVideoFrame : public VideoFrame {
void InitToEmptyBuffer(int w, int h, size_t pixel_width, size_t pixel_height,
int64_t time_stamp_ns);
- // TODO(magjed): Remove once Chromium is updated.
- bool InitToBlack(int w, int h, size_t pixel_width, size_t pixel_height,
- int64_t elapsed_time_ns, int64_t time_stamp_ns);
-
bool InitToBlack(int w, int h, size_t pixel_width, size_t pixel_height,
int64_t time_stamp_ns) override;
diff --git a/talk/media/webrtc/webrtcvoe.h b/talk/media/webrtc/webrtcvoe.h
index db6a64a1fe..aa705a014d 100644
--- a/talk/media/webrtc/webrtcvoe.h
+++ b/talk/media/webrtc/webrtcvoe.h
@@ -36,7 +36,6 @@
#include "webrtc/voice_engine/include/voe_audio_processing.h"
#include "webrtc/voice_engine/include/voe_base.h"
#include "webrtc/voice_engine/include/voe_codec.h"
-#include "webrtc/voice_engine/include/voe_dtmf.h"
#include "webrtc/voice_engine/include/voe_errors.h"
#include "webrtc/voice_engine/include/voe_hardware.h"
#include "webrtc/voice_engine/include/voe_network.h"
@@ -91,14 +90,13 @@ class VoEWrapper {
public:
VoEWrapper()
: engine_(webrtc::VoiceEngine::Create()), processing_(engine_),
- base_(engine_), codec_(engine_), dtmf_(engine_),
+ base_(engine_), codec_(engine_),
hw_(engine_), network_(engine_),
rtp_(engine_), volume_(engine_) {
}
VoEWrapper(webrtc::VoEAudioProcessing* processing,
webrtc::VoEBase* base,
webrtc::VoECodec* codec,
- webrtc::VoEDtmf* dtmf,
webrtc::VoEHardware* hw,
webrtc::VoENetwork* network,
webrtc::VoERTP_RTCP* rtp,
@@ -107,7 +105,6 @@ class VoEWrapper {
processing_(processing),
base_(base),
codec_(codec),
- dtmf_(dtmf),
hw_(hw),
network_(network),
rtp_(rtp),
@@ -118,7 +115,6 @@ class VoEWrapper {
webrtc::VoEAudioProcessing* processing() const { return processing_.get(); }
webrtc::VoEBase* base() const { return base_.get(); }
webrtc::VoECodec* codec() const { return codec_.get(); }
- webrtc::VoEDtmf* dtmf() const { return dtmf_.get(); }
webrtc::VoEHardware* hw() const { return hw_.get(); }
webrtc::VoENetwork* network() const { return network_.get(); }
webrtc::VoERTP_RTCP* rtp() const { return rtp_.get(); }
@@ -130,29 +126,11 @@ class VoEWrapper {
scoped_voe_ptr<webrtc::VoEAudioProcessing> processing_;
scoped_voe_ptr<webrtc::VoEBase> base_;
scoped_voe_ptr<webrtc::VoECodec> codec_;
- scoped_voe_ptr<webrtc::VoEDtmf> dtmf_;
scoped_voe_ptr<webrtc::VoEHardware> hw_;
scoped_voe_ptr<webrtc::VoENetwork> network_;
scoped_voe_ptr<webrtc::VoERTP_RTCP> rtp_;
scoped_voe_ptr<webrtc::VoEVolumeControl> volume_;
};
-
-// Adds indirection to static WebRtc functions, allowing them to be mocked.
-class VoETraceWrapper {
- public:
- virtual ~VoETraceWrapper() {}
-
- virtual int SetTraceFilter(const unsigned int filter) {
- return webrtc::VoiceEngine::SetTraceFilter(filter);
- }
- virtual int SetTraceFile(const char* fileNameUTF8) {
- return webrtc::VoiceEngine::SetTraceFile(fileNameUTF8);
- }
- virtual int SetTraceCallback(webrtc::TraceCallback* callback) {
- return webrtc::VoiceEngine::SetTraceCallback(callback);
- }
-};
-
} // namespace cricket
#endif // TALK_MEDIA_WEBRTCVOE_H_
diff --git a/talk/media/webrtc/webrtcvoiceengine.cc b/talk/media/webrtc/webrtcvoiceengine.cc
index 27ca1deb2d..9192b72539 100644
--- a/talk/media/webrtc/webrtcvoiceengine.cc
+++ b/talk/media/webrtc/webrtcvoiceengine.cc
@@ -42,7 +42,10 @@
#include "talk/media/base/audiorenderer.h"
#include "talk/media/base/constants.h"
#include "talk/media/base/streamparams.h"
+#include "talk/media/webrtc/webrtcmediaengine.h"
#include "talk/media/webrtc/webrtcvoe.h"
+#include "webrtc/audio/audio_sink.h"
+#include "webrtc/base/arraysize.h"
#include "webrtc/base/base64.h"
#include "webrtc/base/byteorder.h"
#include "webrtc/base/common.h"
@@ -52,53 +55,26 @@
#include "webrtc/base/stringutils.h"
#include "webrtc/call/rtc_event_log.h"
#include "webrtc/common.h"
+#include "webrtc/modules/audio_coding/acm2/rent_a_codec.h"
#include "webrtc/modules/audio_processing/include/audio_processing.h"
#include "webrtc/system_wrappers/include/field_trial.h"
+#include "webrtc/system_wrappers/include/trace.h"
namespace cricket {
namespace {
-const int kMaxNumPacketSize = 6;
-struct CodecPref {
- const char* name;
- int clockrate;
- int channels;
- int payload_type;
- bool is_multi_rate;
- int packet_sizes_ms[kMaxNumPacketSize];
-};
-// Note: keep the supported packet sizes in ascending order.
-const CodecPref kCodecPrefs[] = {
- { kOpusCodecName, 48000, 2, 111, true, { 10, 20, 40, 60 } },
- { kIsacCodecName, 16000, 1, 103, true, { 30, 60 } },
- { kIsacCodecName, 32000, 1, 104, true, { 30 } },
- // G722 should be advertised as 8000 Hz because of the RFC "bug".
- { kG722CodecName, 8000, 1, 9, false, { 10, 20, 30, 40, 50, 60 } },
- { kIlbcCodecName, 8000, 1, 102, false, { 20, 30, 40, 60 } },
- { kPcmuCodecName, 8000, 1, 0, false, { 10, 20, 30, 40, 50, 60 } },
- { kPcmaCodecName, 8000, 1, 8, false, { 10, 20, 30, 40, 50, 60 } },
- { kCnCodecName, 32000, 1, 106, false, { } },
- { kCnCodecName, 16000, 1, 105, false, { } },
- { kCnCodecName, 8000, 1, 13, false, { } },
- { kRedCodecName, 8000, 1, 127, false, { } },
- { kDtmfCodecName, 8000, 1, 126, false, { } },
-};
+const int kDefaultTraceFilter = webrtc::kTraceNone | webrtc::kTraceTerseInfo |
+ webrtc::kTraceWarning | webrtc::kTraceError |
+ webrtc::kTraceCritical;
+const int kElevatedTraceFilter = kDefaultTraceFilter | webrtc::kTraceStateInfo |
+ webrtc::kTraceInfo;
-// For Linux/Mac, using the default device is done by specifying index 0 for
-// VoE 4.0 and not -1 (which was the case for VoE 3.5).
-//
// On Windows Vista and newer, Microsoft introduced the concept of "Default
// Communications Device". This means that there are two types of default
// devices (old Wave Audio style default and Default Communications Device).
//
// On Windows systems which only support Wave Audio style default, uses either
// -1 or 0 to select the default device.
-//
-// On Windows systems which support both "Default Communication Device" and
-// old Wave Audio style default, use -1 for Default Communications Device and
-// -2 for Wave Audio style default, which is what we want to use for clips.
-// It's not clear yet whether the -2 index is handled properly on other OSes.
-
#ifdef WIN32
const int kDefaultAudioDeviceId = -1;
#else
@@ -150,6 +126,12 @@ const char kAecDumpByAudioOptionFilename[] = "/sdcard/audio.aecdump";
const char kAecDumpByAudioOptionFilename[] = "audio.aecdump";
#endif
+// Constants from voice_engine_defines.h.
+const int kMinTelephoneEventCode = 0; // RFC4733 (Section 2.3.1)
+const int kMaxTelephoneEventCode = 255;
+const int kMinTelephoneEventDuration = 100;
+const int kMaxTelephoneEventDuration = 60000; // Actual limit is 2^16
+
bool ValidateStreamParams(const StreamParams& sp) {
if (sp.ssrcs.empty()) {
LOG(LS_ERROR) << "No SSRCs in stream parameters: " << sp.ToString();
@@ -177,32 +159,6 @@ std::string ToString(const webrtc::CodecInst& codec) {
return ss.str();
}
-void LogMultiline(rtc::LoggingSeverity sev, char* text) {
- const char* delim = "\r\n";
- for (char* tok = strtok(text, delim); tok; tok = strtok(NULL, delim)) {
- LOG_V(sev) << tok;
- }
-}
-
-// Severity is an integer because it comes is assumed to be from command line.
-int SeverityToFilter(int severity) {
- int filter = webrtc::kTraceNone;
- switch (severity) {
- case rtc::LS_VERBOSE:
- filter |= webrtc::kTraceAll;
- FALLTHROUGH();
- case rtc::LS_INFO:
- filter |= (webrtc::kTraceStateInfo | webrtc::kTraceInfo);
- FALLTHROUGH();
- case rtc::LS_WARNING:
- filter |= (webrtc::kTraceTerseInfo | webrtc::kTraceWarning);
- FALLTHROUGH();
- case rtc::LS_ERROR:
- filter |= (webrtc::kTraceError | webrtc::kTraceCritical);
- }
- return filter;
-}
-
bool IsCodec(const AudioCodec& codec, const char* ref_name) {
return (_stricmp(codec.name.c_str(), ref_name) == 0);
}
@@ -211,19 +167,9 @@ bool IsCodec(const webrtc::CodecInst& codec, const char* ref_name) {
return (_stricmp(codec.plname, ref_name) == 0);
}
-bool IsCodecMultiRate(const webrtc::CodecInst& codec) {
- for (size_t i = 0; i < ARRAY_SIZE(kCodecPrefs); ++i) {
- if (IsCodec(codec, kCodecPrefs[i].name) &&
- kCodecPrefs[i].clockrate == codec.plfreq) {
- return kCodecPrefs[i].is_multi_rate;
- }
- }
- return false;
-}
-
bool FindCodec(const std::vector<AudioCodec>& codecs,
- const AudioCodec& codec,
- AudioCodec* found_codec) {
+ const AudioCodec& codec,
+ AudioCodec* found_codec) {
for (const AudioCodec& c : codecs) {
if (c.Matches(codec)) {
if (found_codec != NULL) {
@@ -253,38 +199,8 @@ bool IsNackEnabled(const AudioCodec& codec) {
kParamValueEmpty));
}
-int SelectPacketSize(const CodecPref& codec_pref, int ptime_ms) {
- int selected_packet_size_ms = codec_pref.packet_sizes_ms[0];
- for (int packet_size_ms : codec_pref.packet_sizes_ms) {
- if (packet_size_ms && packet_size_ms <= ptime_ms) {
- selected_packet_size_ms = packet_size_ms;
- }
- }
- return selected_packet_size_ms;
-}
-
-// If the AudioCodec param kCodecParamPTime is set, then we will set it to codec
-// pacsize if it's valid, or we will pick the next smallest value we support.
-// TODO(Brave): Query supported packet sizes from ACM when the API is ready.
-bool SetPTimeAsPacketSize(webrtc::CodecInst* codec, int ptime_ms) {
- for (const CodecPref& codec_pref : kCodecPrefs) {
- if ((IsCodec(*codec, codec_pref.name) &&
- codec_pref.clockrate == codec->plfreq) ||
- IsCodec(*codec, kG722CodecName)) {
- int packet_size_ms = SelectPacketSize(codec_pref, ptime_ms);
- if (packet_size_ms) {
- // Convert unit from milli-seconds to samples.
- codec->pacsize = (codec->plfreq / 1000) * packet_size_ms;
- return true;
- }
- }
- }
- return false;
-}
-
// Return true if codec.params[feature] == "1", false otherwise.
-bool IsCodecFeatureEnabled(const AudioCodec& codec,
- const char* feature) {
+bool IsCodecFeatureEnabled(const AudioCodec& codec, const char* feature) {
int value;
return codec.GetParam(feature, &value) && value == 1;
}
@@ -351,109 +267,29 @@ void GetOpusConfig(const AudioCodec& codec, webrtc::CodecInst* voe_codec,
voe_codec->rate = GetOpusBitrate(codec, *max_playback_rate);
}
-// Changes RTP timestamp rate of G722. This is due to the "bug" in the RFC
-// which says that G722 should be advertised as 8 kHz although it is a 16 kHz
-// codec.
-void MaybeFixupG722(webrtc::CodecInst* voe_codec, int new_plfreq) {
- if (IsCodec(*voe_codec, kG722CodecName)) {
- // If the ASSERT triggers, the codec definition in WebRTC VoiceEngine
- // has changed, and this special case is no longer needed.
- RTC_DCHECK(voe_codec->plfreq != new_plfreq);
- voe_codec->plfreq = new_plfreq;
- }
-}
-
-// Gets the default set of options applied to the engine. Historically, these
-// were supplied as a combination of flags from the channel manager (ec, agc,
-// ns, and highpass) and the rest hardcoded in InitInternal.
-AudioOptions GetDefaultEngineOptions() {
- AudioOptions options;
- options.echo_cancellation.Set(true);
- options.auto_gain_control.Set(true);
- options.noise_suppression.Set(true);
- options.highpass_filter.Set(true);
- options.stereo_swapping.Set(false);
- options.audio_jitter_buffer_max_packets.Set(50);
- options.audio_jitter_buffer_fast_accelerate.Set(false);
- options.typing_detection.Set(true);
- options.adjust_agc_delta.Set(0);
- options.experimental_agc.Set(false);
- options.extended_filter_aec.Set(false);
- options.delay_agnostic_aec.Set(false);
- options.experimental_ns.Set(false);
- options.aec_dump.Set(false);
- return options;
-}
-
-std::string GetEnableString(bool enable) {
- return enable ? "enable" : "disable";
-}
-} // namespace {
-
-WebRtcVoiceEngine::WebRtcVoiceEngine()
- : voe_wrapper_(new VoEWrapper()),
- tracing_(new VoETraceWrapper()),
- adm_(NULL),
- log_filter_(SeverityToFilter(kDefaultLogSeverity)),
- is_dumping_aec_(false) {
- Construct();
-}
-
-WebRtcVoiceEngine::WebRtcVoiceEngine(VoEWrapper* voe_wrapper,
- VoETraceWrapper* tracing)
- : voe_wrapper_(voe_wrapper),
- tracing_(tracing),
- adm_(NULL),
- log_filter_(SeverityToFilter(kDefaultLogSeverity)),
- is_dumping_aec_(false) {
- Construct();
-}
-
-void WebRtcVoiceEngine::Construct() {
- SetTraceFilter(log_filter_);
- initialized_ = false;
- LOG(LS_VERBOSE) << "WebRtcVoiceEngine::WebRtcVoiceEngine";
- SetTraceOptions("");
- if (tracing_->SetTraceCallback(this) == -1) {
- LOG_RTCERR0(SetTraceCallback);
- }
- if (voe_wrapper_->base()->RegisterVoiceEngineObserver(*this) == -1) {
- LOG_RTCERR0(RegisterVoiceEngineObserver);
- }
- // Clear the default agc state.
- memset(&default_agc_config_, 0, sizeof(default_agc_config_));
-
- // Load our audio codec list.
- ConstructCodecs();
-
- // Load our RTP Header extensions.
- rtp_header_extensions_.push_back(
- RtpHeaderExtension(kRtpAudioLevelHeaderExtension,
- kRtpAudioLevelHeaderExtensionDefaultId));
- rtp_header_extensions_.push_back(
- RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension,
- kRtpAbsoluteSenderTimeHeaderExtensionDefaultId));
- if (webrtc::field_trial::FindFullName("WebRTC-SendSideBwe") == "Enabled") {
- rtp_header_extensions_.push_back(RtpHeaderExtension(
- kRtpTransportSequenceNumberHeaderExtension,
- kRtpTransportSequenceNumberHeaderExtensionDefaultId));
- }
- options_ = GetDefaultEngineOptions();
+webrtc::AudioState::Config MakeAudioStateConfig(VoEWrapper* voe_wrapper) {
+ webrtc::AudioState::Config config;
+ config.voice_engine = voe_wrapper->engine();
+ return config;
}
-void WebRtcVoiceEngine::ConstructCodecs() {
- LOG(LS_INFO) << "WebRtc VoiceEngine codecs:";
- int ncodecs = voe_wrapper_->codec()->NumOfCodecs();
- for (int i = 0; i < ncodecs; ++i) {
- webrtc::CodecInst voe_codec;
- if (GetVoeCodec(i, &voe_codec)) {
+class WebRtcVoiceCodecs final {
+ public:
+ // TODO(solenberg): Do this filtering once off-line, add a simple AudioCodec
+ // list and add a test which verifies VoE supports the listed codecs.
+ static std::vector<AudioCodec> SupportedCodecs() {
+ LOG(LS_INFO) << "WebRtc VoiceEngine codecs:";
+ std::vector<AudioCodec> result;
+ for (webrtc::CodecInst voe_codec : webrtc::acm2::RentACodec::Database()) {
+ // Change the sample rate of G722 to 8000 to match SDP.
+ MaybeFixupG722(&voe_codec, 8000);
// Skip uncompressed formats.
if (IsCodec(voe_codec, kL16CodecName)) {
continue;
}
const CodecPref* pref = NULL;
- for (size_t j = 0; j < ARRAY_SIZE(kCodecPrefs); ++j) {
+ for (size_t j = 0; j < arraysize(kCodecPrefs); ++j) {
if (IsCodec(voe_codec, kCodecPrefs[j].name) &&
kCodecPrefs[j].clockrate == voe_codec.plfreq &&
kCodecPrefs[j].channels == voe_codec.channels) {
@@ -465,9 +301,10 @@ void WebRtcVoiceEngine::ConstructCodecs() {
if (pref) {
// Use the payload type that we've configured in our pref table;
// use the offset in our pref table to determine the sort order.
- AudioCodec codec(pref->payload_type, voe_codec.plname, voe_codec.plfreq,
- voe_codec.rate, voe_codec.channels,
- ARRAY_SIZE(kCodecPrefs) - (pref - kCodecPrefs));
+ AudioCodec codec(
+ pref->payload_type, voe_codec.plname, voe_codec.plfreq,
+ voe_codec.rate, voe_codec.channels,
+ static_cast<int>(arraysize(kCodecPrefs)) - (pref - kCodecPrefs));
LOG(LS_INFO) << ToString(codec);
if (IsCodec(codec, kIsacCodecName)) {
// Indicate auto-bitrate in signaling.
@@ -488,40 +325,183 @@ void WebRtcVoiceEngine::ConstructCodecs() {
// TODO(hellner): Add ptime, sprop-stereo, and stereo
// when they can be set to values other than the default.
}
- codecs_.push_back(codec);
+ result.push_back(codec);
} else {
LOG(LS_WARNING) << "Unexpected codec: " << ToString(voe_codec);
}
}
+ // Make sure they are in local preference order.
+ std::sort(result.begin(), result.end(), &AudioCodec::Preferable);
+ return result;
+ }
+
+ static bool ToCodecInst(const AudioCodec& in,
+ webrtc::CodecInst* out) {
+ for (webrtc::CodecInst voe_codec : webrtc::acm2::RentACodec::Database()) {
+ // Change the sample rate of G722 to 8000 to match SDP.
+ MaybeFixupG722(&voe_codec, 8000);
+ AudioCodec codec(voe_codec.pltype, voe_codec.plname, voe_codec.plfreq,
+ voe_codec.rate, voe_codec.channels, 0);
+ bool multi_rate = IsCodecMultiRate(voe_codec);
+ // Allow arbitrary rates for ISAC to be specified.
+ if (multi_rate) {
+ // Set codec.bitrate to 0 so the check for codec.Matches() passes.
+ codec.bitrate = 0;
+ }
+ if (codec.Matches(in)) {
+ if (out) {
+ // Fixup the payload type.
+ voe_codec.pltype = in.id;
+
+ // Set bitrate if specified.
+ if (multi_rate && in.bitrate != 0) {
+ voe_codec.rate = in.bitrate;
+ }
+
+ // Reset G722 sample rate to 16000 to match WebRTC.
+ MaybeFixupG722(&voe_codec, 16000);
+
+ // Apply codec-specific settings.
+ if (IsCodec(codec, kIsacCodecName)) {
+ // If ISAC and an explicit bitrate is not specified,
+ // enable auto bitrate adjustment.
+ voe_codec.rate = (in.bitrate > 0) ? in.bitrate : -1;
+ }
+ *out = voe_codec;
+ }
+ return true;
+ }
+ }
+ return false;
}
- // Make sure they are in local preference order.
- std::sort(codecs_.begin(), codecs_.end(), &AudioCodec::Preferable);
-}
-bool WebRtcVoiceEngine::GetVoeCodec(int index, webrtc::CodecInst* codec) {
- if (voe_wrapper_->codec()->GetCodec(index, *codec) == -1) {
+ static bool IsCodecMultiRate(const webrtc::CodecInst& codec) {
+ for (size_t i = 0; i < arraysize(kCodecPrefs); ++i) {
+ if (IsCodec(codec, kCodecPrefs[i].name) &&
+ kCodecPrefs[i].clockrate == codec.plfreq) {
+ return kCodecPrefs[i].is_multi_rate;
+ }
+ }
return false;
}
- // Change the sample rate of G722 to 8000 to match SDP.
- MaybeFixupG722(codec, 8000);
- return true;
+
+ // If the AudioCodec param kCodecParamPTime is set, then we will set it to
+ // codec pacsize if it's valid, or we will pick the next smallest value we
+ // support.
+ // TODO(Brave): Query supported packet sizes from ACM when the API is ready.
+ static bool SetPTimeAsPacketSize(webrtc::CodecInst* codec, int ptime_ms) {
+ for (const CodecPref& codec_pref : kCodecPrefs) {
+ if ((IsCodec(*codec, codec_pref.name) &&
+ codec_pref.clockrate == codec->plfreq) ||
+ IsCodec(*codec, kG722CodecName)) {
+ int packet_size_ms = SelectPacketSize(codec_pref, ptime_ms);
+ if (packet_size_ms) {
+ // Convert unit from milli-seconds to samples.
+ codec->pacsize = (codec->plfreq / 1000) * packet_size_ms;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private:
+ static const int kMaxNumPacketSize = 6;
+ struct CodecPref {
+ const char* name;
+ int clockrate;
+ size_t channels;
+ int payload_type;
+ bool is_multi_rate;
+ int packet_sizes_ms[kMaxNumPacketSize];
+ };
+ // Note: keep the supported packet sizes in ascending order.
+ static const CodecPref kCodecPrefs[12];
+
+ static int SelectPacketSize(const CodecPref& codec_pref, int ptime_ms) {
+ int selected_packet_size_ms = codec_pref.packet_sizes_ms[0];
+ for (int packet_size_ms : codec_pref.packet_sizes_ms) {
+ if (packet_size_ms && packet_size_ms <= ptime_ms) {
+ selected_packet_size_ms = packet_size_ms;
+ }
+ }
+ return selected_packet_size_ms;
+ }
+
+ // Changes RTP timestamp rate of G722. This is due to the "bug" in the RFC
+ // which says that G722 should be advertised as 8 kHz although it is a 16 kHz
+ // codec.
+ static void MaybeFixupG722(webrtc::CodecInst* voe_codec, int new_plfreq) {
+ if (IsCodec(*voe_codec, kG722CodecName)) {
+ // If the ASSERT triggers, the codec definition in WebRTC VoiceEngine
+ // has changed, and this special case is no longer needed.
+ RTC_DCHECK(voe_codec->plfreq != new_plfreq);
+ voe_codec->plfreq = new_plfreq;
+ }
+ }
+};
+
+const WebRtcVoiceCodecs::CodecPref WebRtcVoiceCodecs::kCodecPrefs[12] = {
+ { kOpusCodecName, 48000, 2, 111, true, { 10, 20, 40, 60 } },
+ { kIsacCodecName, 16000, 1, 103, true, { 30, 60 } },
+ { kIsacCodecName, 32000, 1, 104, true, { 30 } },
+ // G722 should be advertised as 8000 Hz because of the RFC "bug".
+ { kG722CodecName, 8000, 1, 9, false, { 10, 20, 30, 40, 50, 60 } },
+ { kIlbcCodecName, 8000, 1, 102, false, { 20, 30, 40, 60 } },
+ { kPcmuCodecName, 8000, 1, 0, false, { 10, 20, 30, 40, 50, 60 } },
+ { kPcmaCodecName, 8000, 1, 8, false, { 10, 20, 30, 40, 50, 60 } },
+ { kCnCodecName, 32000, 1, 106, false, { } },
+ { kCnCodecName, 16000, 1, 105, false, { } },
+ { kCnCodecName, 8000, 1, 13, false, { } },
+ { kRedCodecName, 8000, 1, 127, false, { } },
+ { kDtmfCodecName, 8000, 1, 126, false, { } },
+};
+} // namespace {
+
+bool WebRtcVoiceEngine::ToCodecInst(const AudioCodec& in,
+ webrtc::CodecInst* out) {
+ return WebRtcVoiceCodecs::ToCodecInst(in, out);
+}
+
+WebRtcVoiceEngine::WebRtcVoiceEngine()
+ : voe_wrapper_(new VoEWrapper()),
+ audio_state_(webrtc::AudioState::Create(MakeAudioStateConfig(voe()))) {
+ Construct();
+}
+
+WebRtcVoiceEngine::WebRtcVoiceEngine(VoEWrapper* voe_wrapper)
+ : voe_wrapper_(voe_wrapper) {
+ Construct();
+}
+
+void WebRtcVoiceEngine::Construct() {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ LOG(LS_VERBOSE) << "WebRtcVoiceEngine::WebRtcVoiceEngine";
+
+ signal_thread_checker_.DetachFromThread();
+ std::memset(&default_agc_config_, 0, sizeof(default_agc_config_));
+ voe_config_.Set<webrtc::VoicePacing>(new webrtc::VoicePacing(true));
+
+ webrtc::Trace::set_level_filter(kDefaultTraceFilter);
+ webrtc::Trace::SetTraceCallback(this);
+
+ // Load our audio codec list.
+ codecs_ = WebRtcVoiceCodecs::SupportedCodecs();
}
WebRtcVoiceEngine::~WebRtcVoiceEngine() {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
LOG(LS_VERBOSE) << "WebRtcVoiceEngine::~WebRtcVoiceEngine";
- if (voe_wrapper_->base()->DeRegisterVoiceEngineObserver() == -1) {
- LOG_RTCERR0(DeRegisterVoiceEngineObserver);
- }
if (adm_) {
voe_wrapper_.reset();
adm_->Release();
adm_ = NULL;
}
-
- tracing_->SetTraceCallback(NULL);
+ webrtc::Trace::SetTraceCallback(nullptr);
}
bool WebRtcVoiceEngine::Init(rtc::Thread* worker_thread) {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread == rtc::Thread::Current());
LOG(LS_INFO) << "WebRtcVoiceEngine::Init";
bool res = InitInternal();
@@ -535,59 +515,37 @@ bool WebRtcVoiceEngine::Init(rtc::Thread* worker_thread) {
}
bool WebRtcVoiceEngine::InitInternal() {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
// Temporarily turn logging level up for the Init call
- int old_filter = log_filter_;
- int extended_filter = log_filter_ | SeverityToFilter(rtc::LS_INFO);
- SetTraceFilter(extended_filter);
- SetTraceOptions("");
-
- // Init WebRtc VoiceEngine.
+ webrtc::Trace::set_level_filter(kElevatedTraceFilter);
+ LOG(LS_INFO) << webrtc::VoiceEngine::GetVersionString();
if (voe_wrapper_->base()->Init(adm_) == -1) {
LOG_RTCERR0_EX(Init, voe_wrapper_->error());
- SetTraceFilter(old_filter);
return false;
}
-
- SetTraceFilter(old_filter);
- SetTraceOptions(log_options_);
-
- // Log the VoiceEngine version info
- char buffer[1024] = "";
- voe_wrapper_->base()->GetVersion(buffer);
- LOG(LS_INFO) << "WebRtc VoiceEngine Version:";
- LogMultiline(rtc::LS_INFO, buffer);
+ webrtc::Trace::set_level_filter(kDefaultTraceFilter);
// Save the default AGC configuration settings. This must happen before
- // calling SetOptions or the default will be overwritten.
+ // calling ApplyOptions or the default will be overwritten.
if (voe_wrapper_->processing()->GetAgcConfig(default_agc_config_) == -1) {
LOG_RTCERR0(GetAgcConfig);
return false;
}
- // Set defaults for options, so that ApplyOptions applies them explicitly
- // when we clear option (channel) overrides. External clients can still
- // modify the defaults via SetOptions (on the media engine).
- if (!SetOptions(GetDefaultEngineOptions())) {
- return false;
- }
-
// Print our codec list again for the call diagnostic log
LOG(LS_INFO) << "WebRtc VoiceEngine codecs:";
for (const AudioCodec& codec : codecs_) {
LOG(LS_INFO) << ToString(codec);
}
- // Disable the DTMF playout when a tone is sent.
- // PlayDtmfTone will be used if local playout is needed.
- if (voe_wrapper_->dtmf()->SetDtmfFeedbackStatus(false) == -1) {
- LOG_RTCERR1(SetDtmfFeedbackStatus, false);
- }
+ SetDefaultDevices();
initialized_ = true;
return true;
}
void WebRtcVoiceEngine::Terminate() {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
LOG(LS_INFO) << "WebRtcVoiceEngine::Terminate";
initialized_ = false;
@@ -596,62 +554,81 @@ void WebRtcVoiceEngine::Terminate() {
voe_wrapper_->base()->Terminate();
}
+rtc::scoped_refptr<webrtc::AudioState>
+ WebRtcVoiceEngine::GetAudioState() const {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ return audio_state_;
+}
+
VoiceMediaChannel* WebRtcVoiceEngine::CreateChannel(webrtc::Call* call,
const AudioOptions& options) {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return new WebRtcVoiceMediaChannel(this, options, call);
}
-bool WebRtcVoiceEngine::SetOptions(const AudioOptions& options) {
- if (!ApplyOptions(options)) {
- return false;
- }
- options_ = options;
- return true;
-}
-
-// AudioOptions defaults are set in InitInternal (for options with corresponding
-// MediaEngineInterface flags) and in SetOptions(int) for flagless options.
bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
LOG(LS_INFO) << "ApplyOptions: " << options_in.ToString();
- AudioOptions options = options_in; // The options are modified below.
+
+ // Default engine options.
+ AudioOptions options;
+ options.echo_cancellation = rtc::Optional<bool>(true);
+ options.auto_gain_control = rtc::Optional<bool>(true);
+ options.noise_suppression = rtc::Optional<bool>(true);
+ options.highpass_filter = rtc::Optional<bool>(true);
+ options.stereo_swapping = rtc::Optional<bool>(false);
+ options.audio_jitter_buffer_max_packets = rtc::Optional<int>(50);
+ options.audio_jitter_buffer_fast_accelerate = rtc::Optional<bool>(false);
+ options.typing_detection = rtc::Optional<bool>(true);
+ options.adjust_agc_delta = rtc::Optional<int>(0);
+ options.experimental_agc = rtc::Optional<bool>(false);
+ options.extended_filter_aec = rtc::Optional<bool>(false);
+ options.delay_agnostic_aec = rtc::Optional<bool>(false);
+ options.experimental_ns = rtc::Optional<bool>(false);
+ options.aec_dump = rtc::Optional<bool>(false);
+
+ // Apply any given options on top.
+ options.SetAll(options_in);
+
// kEcConference is AEC with high suppression.
webrtc::EcModes ec_mode = webrtc::kEcConference;
webrtc::AecmModes aecm_mode = webrtc::kAecmSpeakerphone;
webrtc::AgcModes agc_mode = webrtc::kAgcAdaptiveAnalog;
webrtc::NsModes ns_mode = webrtc::kNsHighSuppression;
- bool aecm_comfort_noise = false;
- if (options.aecm_generate_comfort_noise.Get(&aecm_comfort_noise)) {
+ if (options.aecm_generate_comfort_noise) {
LOG(LS_VERBOSE) << "Comfort noise explicitly set to "
- << aecm_comfort_noise << " (default is false).";
+ << *options.aecm_generate_comfort_noise
+ << " (default is false).";
}
-#if defined(IOS)
+#if defined(WEBRTC_IOS)
// On iOS, VPIO provides built-in EC and AGC.
- options.echo_cancellation.Set(false);
- options.auto_gain_control.Set(false);
+ options.echo_cancellation = rtc::Optional<bool>(false);
+ options.auto_gain_control = rtc::Optional<bool>(false);
LOG(LS_INFO) << "Always disable AEC and AGC on iOS. Use built-in instead.";
#elif defined(ANDROID)
ec_mode = webrtc::kEcAecm;
#endif
-#if defined(IOS) || defined(ANDROID)
+#if defined(WEBRTC_IOS) || defined(ANDROID)
// Set the AGC mode for iOS as well despite disabling it above, to avoid
// unsupported configuration errors from webrtc.
agc_mode = webrtc::kAgcFixedDigital;
- options.typing_detection.Set(false);
- options.experimental_agc.Set(false);
- options.extended_filter_aec.Set(false);
- options.experimental_ns.Set(false);
+ options.typing_detection = rtc::Optional<bool>(false);
+ options.experimental_agc = rtc::Optional<bool>(false);
+ options.extended_filter_aec = rtc::Optional<bool>(false);
+ options.experimental_ns = rtc::Optional<bool>(false);
#endif
// Delay Agnostic AEC automatically turns on EC if not set except on iOS
// where the feature is not supported.
bool use_delay_agnostic_aec = false;
-#if !defined(IOS)
- if (options.delay_agnostic_aec.Get(&use_delay_agnostic_aec)) {
+#if !defined(WEBRTC_IOS)
+ if (options.delay_agnostic_aec) {
+ use_delay_agnostic_aec = *options.delay_agnostic_aec;
if (use_delay_agnostic_aec) {
- options.echo_cancellation.Set(true);
- options.extended_filter_aec.Set(true);
+ options.echo_cancellation = rtc::Optional<bool>(true);
+ options.extended_filter_aec = rtc::Optional<bool>(true);
ec_mode = webrtc::kEcConference;
}
}
@@ -659,8 +636,7 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
webrtc::VoEAudioProcessing* voep = voe_wrapper_->processing();
- bool echo_cancellation = false;
- if (options.echo_cancellation.Get(&echo_cancellation)) {
+ if (options.echo_cancellation) {
// Check if platform supports built-in EC. Currently only supported on
// Android and in combination with Java based audio layer.
// TODO(henrika): investigate possibility to support built-in EC also
@@ -671,63 +647,61 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
// overriding it. Enable/Disable it according to the echo_cancellation
// audio option.
const bool enable_built_in_aec =
- echo_cancellation && !use_delay_agnostic_aec;
+ *options.echo_cancellation && !use_delay_agnostic_aec;
if (voe_wrapper_->hw()->EnableBuiltInAEC(enable_built_in_aec) == 0 &&
enable_built_in_aec) {
// Disable internal software EC if built-in EC is enabled,
// i.e., replace the software EC with the built-in EC.
- options.echo_cancellation.Set(false);
- echo_cancellation = false;
+ options.echo_cancellation = rtc::Optional<bool>(false);
LOG(LS_INFO) << "Disabling EC since built-in EC will be used instead";
}
}
- if (voep->SetEcStatus(echo_cancellation, ec_mode) == -1) {
- LOG_RTCERR2(SetEcStatus, echo_cancellation, ec_mode);
+ if (voep->SetEcStatus(*options.echo_cancellation, ec_mode) == -1) {
+ LOG_RTCERR2(SetEcStatus, *options.echo_cancellation, ec_mode);
return false;
} else {
- LOG(LS_INFO) << "Echo control set to " << echo_cancellation
+ LOG(LS_INFO) << "Echo control set to " << *options.echo_cancellation
<< " with mode " << ec_mode;
}
#if !defined(ANDROID)
// TODO(ajm): Remove the error return on Android from webrtc.
- if (voep->SetEcMetricsStatus(echo_cancellation) == -1) {
- LOG_RTCERR1(SetEcMetricsStatus, echo_cancellation);
+ if (voep->SetEcMetricsStatus(*options.echo_cancellation) == -1) {
+ LOG_RTCERR1(SetEcMetricsStatus, *options.echo_cancellation);
return false;
}
#endif
if (ec_mode == webrtc::kEcAecm) {
- if (voep->SetAecmMode(aecm_mode, aecm_comfort_noise) != 0) {
- LOG_RTCERR2(SetAecmMode, aecm_mode, aecm_comfort_noise);
+ bool cn = options.aecm_generate_comfort_noise.value_or(false);
+ if (voep->SetAecmMode(aecm_mode, cn) != 0) {
+ LOG_RTCERR2(SetAecmMode, aecm_mode, cn);
return false;
}
}
}
- bool auto_gain_control = false;
- if (options.auto_gain_control.Get(&auto_gain_control)) {
+ if (options.auto_gain_control) {
const bool built_in_agc = voe_wrapper_->hw()->BuiltInAGCIsAvailable();
if (built_in_agc) {
- if (voe_wrapper_->hw()->EnableBuiltInAGC(auto_gain_control) == 0 &&
- auto_gain_control) {
+ if (voe_wrapper_->hw()->EnableBuiltInAGC(*options.auto_gain_control) ==
+ 0 &&
+ *options.auto_gain_control) {
// Disable internal software AGC if built-in AGC is enabled,
// i.e., replace the software AGC with the built-in AGC.
- options.auto_gain_control.Set(false);
- auto_gain_control = false;
+ options.auto_gain_control = rtc::Optional<bool>(false);
LOG(LS_INFO) << "Disabling AGC since built-in AGC will be used instead";
}
}
- if (voep->SetAgcStatus(auto_gain_control, agc_mode) == -1) {
- LOG_RTCERR2(SetAgcStatus, auto_gain_control, agc_mode);
+ if (voep->SetAgcStatus(*options.auto_gain_control, agc_mode) == -1) {
+ LOG_RTCERR2(SetAgcStatus, *options.auto_gain_control, agc_mode);
return false;
} else {
- LOG(LS_INFO) << "Auto gain set to " << auto_gain_control << " with mode "
- << agc_mode;
+ LOG(LS_INFO) << "Auto gain set to " << *options.auto_gain_control
+ << " with mode " << agc_mode;
}
}
- if (options.tx_agc_target_dbov.IsSet() ||
- options.tx_agc_digital_compression_gain.IsSet() ||
- options.tx_agc_limiter.IsSet()) {
+ if (options.tx_agc_target_dbov || options.tx_agc_digital_compression_gain ||
+ options.tx_agc_limiter) {
// Override default_agc_config_. Generally, an unset option means "leave
// the VoE bits alone" in this function, so we want whatever is set to be
// stored as the new "default". If we didn't, then setting e.g.
@@ -736,15 +710,13 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
// Also, if we don't update default_agc_config_, then adjust_agc_delta
// would be an offset from the original values, and not whatever was set
// explicitly.
- default_agc_config_.targetLeveldBOv =
- options.tx_agc_target_dbov.GetWithDefaultIfUnset(
- default_agc_config_.targetLeveldBOv);
+ default_agc_config_.targetLeveldBOv = options.tx_agc_target_dbov.value_or(
+ default_agc_config_.targetLeveldBOv);
default_agc_config_.digitalCompressionGaindB =
- options.tx_agc_digital_compression_gain.GetWithDefaultIfUnset(
+ options.tx_agc_digital_compression_gain.value_or(
default_agc_config_.digitalCompressionGaindB);
default_agc_config_.limiterEnable =
- options.tx_agc_limiter.GetWithDefaultIfUnset(
- default_agc_config_.limiterEnable);
+ options.tx_agc_limiter.value_or(default_agc_config_.limiterEnable);
if (voe_wrapper_->processing()->SetAgcConfig(default_agc_config_) == -1) {
LOG_RTCERR3(SetAgcConfig,
default_agc_config_.targetLeveldBOv,
@@ -754,84 +726,79 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
}
}
- bool noise_suppression = false;
- if (options.noise_suppression.Get(&noise_suppression)) {
+ if (options.noise_suppression) {
const bool built_in_ns = voe_wrapper_->hw()->BuiltInNSIsAvailable();
if (built_in_ns) {
- if (voe_wrapper_->hw()->EnableBuiltInNS(noise_suppression) == 0 &&
- noise_suppression) {
+ if (voe_wrapper_->hw()->EnableBuiltInNS(*options.noise_suppression) ==
+ 0 &&
+ *options.noise_suppression) {
// Disable internal software NS if built-in NS is enabled,
// i.e., replace the software NS with the built-in NS.
- options.noise_suppression.Set(false);
- noise_suppression = false;
+ options.noise_suppression = rtc::Optional<bool>(false);
LOG(LS_INFO) << "Disabling NS since built-in NS will be used instead";
}
}
- if (voep->SetNsStatus(noise_suppression, ns_mode) == -1) {
- LOG_RTCERR2(SetNsStatus, noise_suppression, ns_mode);
+ if (voep->SetNsStatus(*options.noise_suppression, ns_mode) == -1) {
+ LOG_RTCERR2(SetNsStatus, *options.noise_suppression, ns_mode);
return false;
} else {
- LOG(LS_INFO) << "Noise suppression set to " << noise_suppression
+ LOG(LS_INFO) << "Noise suppression set to " << *options.noise_suppression
<< " with mode " << ns_mode;
}
}
- bool highpass_filter;
- if (options.highpass_filter.Get(&highpass_filter)) {
- LOG(LS_INFO) << "High pass filter enabled? " << highpass_filter;
- if (voep->EnableHighPassFilter(highpass_filter) == -1) {
- LOG_RTCERR1(SetHighpassFilterStatus, highpass_filter);
+ if (options.highpass_filter) {
+ LOG(LS_INFO) << "High pass filter enabled? " << *options.highpass_filter;
+ if (voep->EnableHighPassFilter(*options.highpass_filter) == -1) {
+ LOG_RTCERR1(SetHighpassFilterStatus, *options.highpass_filter);
return false;
}
}
- bool stereo_swapping;
- if (options.stereo_swapping.Get(&stereo_swapping)) {
- LOG(LS_INFO) << "Stereo swapping enabled? " << stereo_swapping;
- voep->EnableStereoChannelSwapping(stereo_swapping);
- if (voep->IsStereoChannelSwappingEnabled() != stereo_swapping) {
- LOG_RTCERR1(EnableStereoChannelSwapping, stereo_swapping);
+ if (options.stereo_swapping) {
+ LOG(LS_INFO) << "Stereo swapping enabled? " << *options.stereo_swapping;
+ voep->EnableStereoChannelSwapping(*options.stereo_swapping);
+ if (voep->IsStereoChannelSwappingEnabled() != *options.stereo_swapping) {
+ LOG_RTCERR1(EnableStereoChannelSwapping, *options.stereo_swapping);
return false;
}
}
- int audio_jitter_buffer_max_packets;
- if (options.audio_jitter_buffer_max_packets.Get(
- &audio_jitter_buffer_max_packets)) {
- LOG(LS_INFO) << "NetEq capacity is " << audio_jitter_buffer_max_packets;
+ if (options.audio_jitter_buffer_max_packets) {
+ LOG(LS_INFO) << "NetEq capacity is "
+ << *options.audio_jitter_buffer_max_packets;
voe_config_.Set<webrtc::NetEqCapacityConfig>(
- new webrtc::NetEqCapacityConfig(audio_jitter_buffer_max_packets));
+ new webrtc::NetEqCapacityConfig(
+ *options.audio_jitter_buffer_max_packets));
}
- bool audio_jitter_buffer_fast_accelerate;
- if (options.audio_jitter_buffer_fast_accelerate.Get(
- &audio_jitter_buffer_fast_accelerate)) {
- LOG(LS_INFO) << "NetEq fast mode? " << audio_jitter_buffer_fast_accelerate;
+ if (options.audio_jitter_buffer_fast_accelerate) {
+ LOG(LS_INFO) << "NetEq fast mode? "
+ << *options.audio_jitter_buffer_fast_accelerate;
voe_config_.Set<webrtc::NetEqFastAccelerate>(
- new webrtc::NetEqFastAccelerate(audio_jitter_buffer_fast_accelerate));
+ new webrtc::NetEqFastAccelerate(
+ *options.audio_jitter_buffer_fast_accelerate));
}
- bool typing_detection;
- if (options.typing_detection.Get(&typing_detection)) {
- LOG(LS_INFO) << "Typing detection is enabled? " << typing_detection;
- if (voep->SetTypingDetectionStatus(typing_detection) == -1) {
+ if (options.typing_detection) {
+ LOG(LS_INFO) << "Typing detection is enabled? "
+ << *options.typing_detection;
+ if (voep->SetTypingDetectionStatus(*options.typing_detection) == -1) {
// In case of error, log the info and continue
- LOG_RTCERR1(SetTypingDetectionStatus, typing_detection);
+ LOG_RTCERR1(SetTypingDetectionStatus, *options.typing_detection);
}
}
- int adjust_agc_delta;
- if (options.adjust_agc_delta.Get(&adjust_agc_delta)) {
- LOG(LS_INFO) << "Adjust agc delta is " << adjust_agc_delta;
- if (!AdjustAgcLevel(adjust_agc_delta)) {
+ if (options.adjust_agc_delta) {
+ LOG(LS_INFO) << "Adjust agc delta is " << *options.adjust_agc_delta;
+ if (!AdjustAgcLevel(*options.adjust_agc_delta)) {
return false;
}
}
- bool aec_dump;
- if (options.aec_dump.Get(&aec_dump)) {
- LOG(LS_INFO) << "Aec dump is enabled? " << aec_dump;
- if (aec_dump)
+ if (options.aec_dump) {
+ LOG(LS_INFO) << "Aec dump is enabled? " << *options.aec_dump;
+ if (*options.aec_dump)
StartAecDump(kAecDumpByAudioOptionFilename);
else
StopAecDump();
@@ -839,28 +806,30 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
webrtc::Config config;
- delay_agnostic_aec_.SetFrom(options.delay_agnostic_aec);
- bool delay_agnostic_aec;
- if (delay_agnostic_aec_.Get(&delay_agnostic_aec)) {
- LOG(LS_INFO) << "Delay agnostic aec is enabled? " << delay_agnostic_aec;
+ if (options.delay_agnostic_aec)
+ delay_agnostic_aec_ = options.delay_agnostic_aec;
+ if (delay_agnostic_aec_) {
+ LOG(LS_INFO) << "Delay agnostic aec is enabled? " << *delay_agnostic_aec_;
config.Set<webrtc::DelayAgnostic>(
- new webrtc::DelayAgnostic(delay_agnostic_aec));
+ new webrtc::DelayAgnostic(*delay_agnostic_aec_));
}
- extended_filter_aec_.SetFrom(options.extended_filter_aec);
- bool extended_filter;
- if (extended_filter_aec_.Get(&extended_filter)) {
- LOG(LS_INFO) << "Extended filter aec is enabled? " << extended_filter;
+ if (options.extended_filter_aec) {
+ extended_filter_aec_ = options.extended_filter_aec;
+ }
+ if (extended_filter_aec_) {
+ LOG(LS_INFO) << "Extended filter aec is enabled? " << *extended_filter_aec_;
config.Set<webrtc::ExtendedFilter>(
- new webrtc::ExtendedFilter(extended_filter));
+ new webrtc::ExtendedFilter(*extended_filter_aec_));
}
- experimental_ns_.SetFrom(options.experimental_ns);
- bool experimental_ns;
- if (experimental_ns_.Get(&experimental_ns)) {
- LOG(LS_INFO) << "Experimental ns is enabled? " << experimental_ns;
+ if (options.experimental_ns) {
+ experimental_ns_ = options.experimental_ns;
+ }
+ if (experimental_ns_) {
+ LOG(LS_INFO) << "Experimental ns is enabled? " << *experimental_ns_;
config.Set<webrtc::ExperimentalNs>(
- new webrtc::ExperimentalNs(experimental_ns));
+ new webrtc::ExperimentalNs(*experimental_ns_));
}
// We check audioproc for the benefit of tests, since FakeWebRtcVoiceEngine
@@ -870,167 +839,58 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
audioproc->SetExtraOptions(config);
}
- uint32_t recording_sample_rate;
- if (options.recording_sample_rate.Get(&recording_sample_rate)) {
- LOG(LS_INFO) << "Recording sample rate is " << recording_sample_rate;
- if (voe_wrapper_->hw()->SetRecordingSampleRate(recording_sample_rate)) {
- LOG_RTCERR1(SetRecordingSampleRate, recording_sample_rate);
+ if (options.recording_sample_rate) {
+ LOG(LS_INFO) << "Recording sample rate is "
+ << *options.recording_sample_rate;
+ if (voe_wrapper_->hw()->SetRecordingSampleRate(
+ *options.recording_sample_rate)) {
+ LOG_RTCERR1(SetRecordingSampleRate, *options.recording_sample_rate);
}
}
- uint32_t playout_sample_rate;
- if (options.playout_sample_rate.Get(&playout_sample_rate)) {
- LOG(LS_INFO) << "Playout sample rate is " << playout_sample_rate;
- if (voe_wrapper_->hw()->SetPlayoutSampleRate(playout_sample_rate)) {
- LOG_RTCERR1(SetPlayoutSampleRate, playout_sample_rate);
+ if (options.playout_sample_rate) {
+ LOG(LS_INFO) << "Playout sample rate is " << *options.playout_sample_rate;
+ if (voe_wrapper_->hw()->SetPlayoutSampleRate(
+ *options.playout_sample_rate)) {
+ LOG_RTCERR1(SetPlayoutSampleRate, *options.playout_sample_rate);
}
}
return true;
}
-// TODO(juberti): Refactor this so that the core logic can be used to set the
-// soundclip device. At that time, reinstate the soundclip pause/resume code.
-bool WebRtcVoiceEngine::SetDevices(const Device* in_device,
- const Device* out_device) {
-#if !defined(IOS)
- int in_id = in_device ? rtc::FromString<int>(in_device->id) :
- kDefaultAudioDeviceId;
- int out_id = out_device ? rtc::FromString<int>(out_device->id) :
- kDefaultAudioDeviceId;
- // The device manager uses -1 as the default device, which was the case for
- // VoE 3.5. VoE 4.0, however, uses 0 as the default in Linux and Mac.
-#ifndef WIN32
- if (-1 == in_id) {
- in_id = kDefaultAudioDeviceId;
- }
- if (-1 == out_id) {
- out_id = kDefaultAudioDeviceId;
- }
-#endif
-
- std::string in_name = (in_id != kDefaultAudioDeviceId) ?
- in_device->name : "Default device";
- std::string out_name = (out_id != kDefaultAudioDeviceId) ?
- out_device->name : "Default device";
- LOG(LS_INFO) << "Setting microphone to (id=" << in_id << ", name=" << in_name
- << ") and speaker to (id=" << out_id << ", name=" << out_name
- << ")";
+void WebRtcVoiceEngine::SetDefaultDevices() {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+#if !defined(WEBRTC_IOS)
+ int in_id = kDefaultAudioDeviceId;
+ int out_id = kDefaultAudioDeviceId;
+ LOG(LS_INFO) << "Setting microphone to (id=" << in_id
+ << ") and speaker to (id=" << out_id << ")";
- // Must also pause all audio playback and capture.
bool ret = true;
- for (WebRtcVoiceMediaChannel* channel : channels_) {
- if (!channel->PausePlayout()) {
- LOG(LS_WARNING) << "Failed to pause playout";
- ret = false;
- }
- if (!channel->PauseSend()) {
- LOG(LS_WARNING) << "Failed to pause send";
- ret = false;
- }
- }
-
- // Find the recording device id in VoiceEngine and set recording device.
- if (!FindWebRtcAudioDeviceId(true, in_name, in_id, &in_id)) {
+ if (voe_wrapper_->hw()->SetRecordingDevice(in_id) == -1) {
+ LOG_RTCERR1(SetRecordingDevice, in_id);
ret = false;
}
- if (ret) {
- if (voe_wrapper_->hw()->SetRecordingDevice(in_id) == -1) {
- LOG_RTCERR2(SetRecordingDevice, in_name, in_id);
- ret = false;
- }
- webrtc::AudioProcessing* ap = voe()->base()->audio_processing();
- if (ap)
- ap->Initialize();
+ webrtc::AudioProcessing* ap = voe()->base()->audio_processing();
+ if (ap) {
+ ap->Initialize();
}
- // Find the playout device id in VoiceEngine and set playout device.
- if (!FindWebRtcAudioDeviceId(false, out_name, out_id, &out_id)) {
- LOG(LS_WARNING) << "Failed to find VoiceEngine device id for " << out_name;
+ if (voe_wrapper_->hw()->SetPlayoutDevice(out_id) == -1) {
+ LOG_RTCERR1(SetPlayoutDevice, out_id);
ret = false;
}
- if (ret) {
- if (voe_wrapper_->hw()->SetPlayoutDevice(out_id) == -1) {
- LOG_RTCERR2(SetPlayoutDevice, out_name, out_id);
- ret = false;
- }
- }
-
- // Resume all audio playback and capture.
- for (WebRtcVoiceMediaChannel* channel : channels_) {
- if (!channel->ResumePlayout()) {
- LOG(LS_WARNING) << "Failed to resume playout";
- ret = false;
- }
- if (!channel->ResumeSend()) {
- LOG(LS_WARNING) << "Failed to resume send";
- ret = false;
- }
- }
if (ret) {
- LOG(LS_INFO) << "Set microphone to (id=" << in_id <<" name=" << in_name
- << ") and speaker to (id="<< out_id << " name=" << out_name
- << ")";
+ LOG(LS_INFO) << "Set microphone to (id=" << in_id
+ << ") and speaker to (id=" << out_id << ")";
}
-
- return ret;
-#else
- return true;
-#endif // !IOS
-}
-
-bool WebRtcVoiceEngine::FindWebRtcAudioDeviceId(
- bool is_input, const std::string& dev_name, int dev_id, int* rtc_id) {
- // In Linux, VoiceEngine uses the same device dev_id as the device manager.
-#if defined(LINUX) || defined(ANDROID)
- *rtc_id = dev_id;
- return true;
-#else
- // In Windows and Mac, we need to find the VoiceEngine device id by name
- // unless the input dev_id is the default device id.
- if (kDefaultAudioDeviceId == dev_id) {
- *rtc_id = dev_id;
- return true;
- }
-
- // Get the number of VoiceEngine audio devices.
- int count = 0;
- if (is_input) {
- if (-1 == voe_wrapper_->hw()->GetNumOfRecordingDevices(count)) {
- LOG_RTCERR0(GetNumOfRecordingDevices);
- return false;
- }
- } else {
- if (-1 == voe_wrapper_->hw()->GetNumOfPlayoutDevices(count)) {
- LOG_RTCERR0(GetNumOfPlayoutDevices);
- return false;
- }
- }
-
- for (int i = 0; i < count; ++i) {
- char name[128];
- char guid[128];
- if (is_input) {
- voe_wrapper_->hw()->GetRecordingDeviceName(i, name, guid);
- LOG(LS_VERBOSE) << "VoiceEngine microphone " << i << ": " << name;
- } else {
- voe_wrapper_->hw()->GetPlayoutDeviceName(i, name, guid);
- LOG(LS_VERBOSE) << "VoiceEngine speaker " << i << ": " << name;
- }
-
- std::string webrtc_name(name);
- if (dev_name.compare(0, webrtc_name.size(), webrtc_name) == 0) {
- *rtc_id = i;
- return true;
- }
- }
- LOG(LS_WARNING) << "VoiceEngine cannot find device: " << dev_name;
- return false;
-#endif
+#endif // !WEBRTC_IOS
}
bool WebRtcVoiceEngine::GetOutputVolume(int* level) {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
unsigned int ulevel;
if (voe_wrapper_->volume()->GetSpeakerVolume(ulevel) == -1) {
LOG_RTCERR1(GetSpeakerVolume, level);
@@ -1041,6 +901,7 @@ bool WebRtcVoiceEngine::GetOutputVolume(int* level) {
}
bool WebRtcVoiceEngine::SetOutputVolume(int level) {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
RTC_DCHECK(level >= 0 && level <= 255);
if (voe_wrapper_->volume()->SetSpeakerVolume(level) == -1) {
LOG_RTCERR1(SetSpeakerVolume, level);
@@ -1050,136 +911,36 @@ bool WebRtcVoiceEngine::SetOutputVolume(int level) {
}
int WebRtcVoiceEngine::GetInputLevel() {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
unsigned int ulevel;
return (voe_wrapper_->volume()->GetSpeechInputLevel(ulevel) != -1) ?
static_cast<int>(ulevel) : -1;
}
const std::vector<AudioCodec>& WebRtcVoiceEngine::codecs() {
+ RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
return codecs_;
}
-bool WebRtcVoiceEngine::FindCodec(const AudioCodec& in) {
- return FindWebRtcCodec(in, NULL);
-}
-
-// Get the VoiceEngine codec that matches |in|, with the supplied settings.
-bool WebRtcVoiceEngine::FindWebRtcCodec(const AudioCodec& in,
- webrtc::CodecInst* out) {
- int ncodecs = voe_wrapper_->codec()->NumOfCodecs();
- for (int i = 0; i < ncodecs; ++i) {
- webrtc::CodecInst voe_codec;
- if (GetVoeCodec(i, &voe_codec)) {
- AudioCodec codec(voe_codec.pltype, voe_codec.plname, voe_codec.plfreq,
- voe_codec.rate, voe_codec.channels, 0);
- bool multi_rate = IsCodecMultiRate(voe_codec);
- // Allow arbitrary rates for ISAC to be specified.
- if (multi_rate) {
- // Set codec.bitrate to 0 so the check for codec.Matches() passes.
- codec.bitrate = 0;
- }
- if (codec.Matches(in)) {
- if (out) {
- // Fixup the payload type.
- voe_codec.pltype = in.id;
-
- // Set bitrate if specified.
- if (multi_rate && in.bitrate != 0) {
- voe_codec.rate = in.bitrate;
- }
-
- // Reset G722 sample rate to 16000 to match WebRTC.
- MaybeFixupG722(&voe_codec, 16000);
-
- // Apply codec-specific settings.
- if (IsCodec(codec, kIsacCodecName)) {
- // If ISAC and an explicit bitrate is not specified,
- // enable auto bitrate adjustment.
- voe_codec.rate = (in.bitrate > 0) ? in.bitrate : -1;
- }
- *out = voe_codec;
- }
- return true;
- }
- }
- }
- return false;
-}
-const std::vector<RtpHeaderExtension>&
-WebRtcVoiceEngine::rtp_header_extensions() const {
- return rtp_header_extensions_;
-}
-
-void WebRtcVoiceEngine::SetLogging(int min_sev, const char* filter) {
- // if min_sev == -1, we keep the current log level.
- if (min_sev >= 0) {
- SetTraceFilter(SeverityToFilter(min_sev));
- }
- log_options_ = filter;
- SetTraceOptions(initialized_ ? log_options_ : "");
+RtpCapabilities WebRtcVoiceEngine::GetCapabilities() const {
+ RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
+ RtpCapabilities capabilities;
+ capabilities.header_extensions.push_back(RtpHeaderExtension(
+ kRtpAudioLevelHeaderExtension, kRtpAudioLevelHeaderExtensionDefaultId));
+ capabilities.header_extensions.push_back(
+ RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension,
+ kRtpAbsoluteSenderTimeHeaderExtensionDefaultId));
+ return capabilities;
}
int WebRtcVoiceEngine::GetLastEngineError() {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return voe_wrapper_->error();
}
-void WebRtcVoiceEngine::SetTraceFilter(int filter) {
- log_filter_ = filter;
- tracing_->SetTraceFilter(filter);
-}
-
-// We suppport three different logging settings for VoiceEngine:
-// 1. Observer callback that goes into talk diagnostic logfile.
-// Use --logfile and --loglevel
-//
-// 2. Encrypted VoiceEngine log for debugging VoiceEngine.
-// Use --voice_loglevel --voice_logfilter "tracefile file_name"
-//
-// 3. EC log and dump for debugging QualityEngine.
-// Use --voice_loglevel --voice_logfilter "recordEC file_name"
-//
-// For more details see: "https://sites.google.com/a/google.com/wavelet/Home/
-// Magic-Flute--RTC-Engine-/Magic-Flute-Command-Line-Parameters"
-void WebRtcVoiceEngine::SetTraceOptions(const std::string& options) {
- // Set encrypted trace file.
- std::vector<std::string> opts;
- rtc::tokenize(options, ' ', '"', '"', &opts);
- std::vector<std::string>::iterator tracefile =
- std::find(opts.begin(), opts.end(), "tracefile");
- if (tracefile != opts.end() && ++tracefile != opts.end()) {
- // Write encrypted debug output (at same loglevel) to file
- // EncryptedTraceFile no longer supported.
- if (tracing_->SetTraceFile(tracefile->c_str()) == -1) {
- LOG_RTCERR1(SetTraceFile, *tracefile);
- }
- }
-
- // Allow trace options to override the trace filter. We default
- // it to log_filter_ (as a translation of libjingle log levels)
- // elsewhere, but this allows clients to explicitly set webrtc
- // log levels.
- std::vector<std::string>::iterator tracefilter =
- std::find(opts.begin(), opts.end(), "tracefilter");
- if (tracefilter != opts.end() && ++tracefilter != opts.end()) {
- if (!tracing_->SetTraceFilter(rtc::FromString<int>(*tracefilter))) {
- LOG_RTCERR1(SetTraceFilter, *tracefilter);
- }
- }
-
- // Set AEC dump file
- std::vector<std::string>::iterator recordEC =
- std::find(opts.begin(), opts.end(), "recordEC");
- if (recordEC != opts.end()) {
- ++recordEC;
- if (recordEC != opts.end())
- StartAecDump(recordEC->c_str());
- else
- StopAecDump();
- }
-}
-
void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace,
int length) {
+ // Note: This callback can happen on any thread!
rtc::LoggingSeverity sev = rtc::LS_VERBOSE;
if (level == webrtc::kTraceError || level == webrtc::kTraceCritical)
sev = rtc::LS_ERROR;
@@ -1201,34 +962,24 @@ void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace,
}
}
-void WebRtcVoiceEngine::CallbackOnError(int channel_id, int err_code) {
- RTC_DCHECK(channel_id == -1);
- LOG(LS_WARNING) << "VoiceEngine error " << err_code << " reported on channel "
- << channel_id << ".";
- rtc::CritScope lock(&channels_cs_);
- for (WebRtcVoiceMediaChannel* channel : channels_) {
- channel->OnError(err_code);
- }
-}
-
void WebRtcVoiceEngine::RegisterChannel(WebRtcVoiceMediaChannel* channel) {
- RTC_DCHECK(channel != NULL);
- rtc::CritScope lock(&channels_cs_);
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(channel);
channels_.push_back(channel);
}
void WebRtcVoiceEngine::UnregisterChannel(WebRtcVoiceMediaChannel* channel) {
- rtc::CritScope lock(&channels_cs_);
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
auto it = std::find(channels_.begin(), channels_.end(), channel);
- if (it != channels_.end()) {
- channels_.erase(it);
- }
+ RTC_DCHECK(it != channels_.end());
+ channels_.erase(it);
}
// Adjusts the default AGC target level by the specified delta.
// NB: If we start messing with other config fields, we'll want
// to save the current webrtc::AgcConfig as well.
bool WebRtcVoiceEngine::AdjustAgcLevel(int delta) {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
webrtc::AgcConfig config = default_agc_config_;
config.targetLeveldBOv -= delta;
@@ -1244,6 +995,7 @@ bool WebRtcVoiceEngine::AdjustAgcLevel(int delta) {
}
bool WebRtcVoiceEngine::SetAudioDeviceModule(webrtc::AudioDeviceModule* adm) {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
if (initialized_) {
LOG(LS_WARNING) << "SetAudioDeviceModule can not be called after Init.";
return false;
@@ -1260,6 +1012,7 @@ bool WebRtcVoiceEngine::SetAudioDeviceModule(webrtc::AudioDeviceModule* adm) {
}
bool WebRtcVoiceEngine::StartAecDump(rtc::PlatformFile file) {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
FILE* aec_dump_file_stream = rtc::FdopenPlatformFileForWriting(file);
if (!aec_dump_file_stream) {
LOG(LS_ERROR) << "Could not open AEC dump file stream.";
@@ -1279,6 +1032,7 @@ bool WebRtcVoiceEngine::StartAecDump(rtc::PlatformFile file) {
}
void WebRtcVoiceEngine::StartAecDump(const std::string& filename) {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
if (!is_dumping_aec_) {
// Start dumping AEC when we are not dumping.
if (voe_wrapper_->processing()->StartDebugRecording(
@@ -1291,6 +1045,7 @@ void WebRtcVoiceEngine::StartAecDump(const std::string& filename) {
}
void WebRtcVoiceEngine::StopAecDump() {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
if (is_dumping_aec_) {
// Stop dumping AEC when we are dumping.
if (voe_wrapper_->processing()->StopDebugRecording() !=
@@ -1302,14 +1057,17 @@ void WebRtcVoiceEngine::StopAecDump() {
}
bool WebRtcVoiceEngine::StartRtcEventLog(rtc::PlatformFile file) {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return voe_wrapper_->codec()->GetEventLog()->StartLogging(file);
}
void WebRtcVoiceEngine::StopRtcEventLog() {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
voe_wrapper_->codec()->GetEventLog()->StopLogging();
}
int WebRtcVoiceEngine::CreateVoEChannel() {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return voe_wrapper_->base()->CreateChannel(voe_config_);
}
@@ -1317,33 +1075,61 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
: public AudioRenderer::Sink {
public:
WebRtcAudioSendStream(int ch, webrtc::AudioTransport* voe_audio_transport,
- uint32_t ssrc, webrtc::Call* call)
- : channel_(ch),
- voe_audio_transport_(voe_audio_transport),
- call_(call) {
+ uint32_t ssrc, const std::string& c_name,
+ const std::vector<webrtc::RtpExtension>& extensions,
+ webrtc::Call* call)
+ : voe_audio_transport_(voe_audio_transport),
+ call_(call),
+ config_(nullptr) {
RTC_DCHECK_GE(ch, 0);
// TODO(solenberg): Once we're not using FakeWebRtcVoiceEngine anymore:
// RTC_DCHECK(voe_audio_transport);
RTC_DCHECK(call);
audio_capture_thread_checker_.DetachFromThread();
- webrtc::AudioSendStream::Config config(nullptr);
- config.voe_channel_id = channel_;
- config.rtp.ssrc = ssrc;
- stream_ = call_->CreateAudioSendStream(config);
- RTC_DCHECK(stream_);
+ config_.rtp.ssrc = ssrc;
+ config_.rtp.c_name = c_name;
+ config_.voe_channel_id = ch;
+ RecreateAudioSendStream(extensions);
}
+
~WebRtcAudioSendStream() override {
- RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Stop();
call_->DestroyAudioSendStream(stream_);
}
+ void RecreateAudioSendStream(
+ const std::vector<webrtc::RtpExtension>& extensions) {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ if (stream_) {
+ call_->DestroyAudioSendStream(stream_);
+ stream_ = nullptr;
+ }
+ config_.rtp.extensions = extensions;
+ RTC_DCHECK(!stream_);
+ stream_ = call_->CreateAudioSendStream(config_);
+ RTC_CHECK(stream_);
+ }
+
+ bool SendTelephoneEvent(int payload_type, uint8_t event,
+ uint32_t duration_ms) {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(stream_);
+ return stream_->SendTelephoneEvent(payload_type, event, duration_ms);
+ }
+
+ webrtc::AudioSendStream::Stats GetStats() const {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(stream_);
+ return stream_->GetStats();
+ }
+
// Starts the rendering by setting a sink to the renderer to get data
// callback.
// This method is called on the libjingle worker thread.
// TODO(xians): Make sure Start() is called only once.
void Start(AudioRenderer* renderer) {
- RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
RTC_DCHECK(renderer);
if (renderer_) {
RTC_DCHECK(renderer_ == renderer);
@@ -1353,16 +1139,11 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
renderer_ = renderer;
}
- webrtc::AudioSendStream::Stats GetStats() const {
- RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
- return stream_->GetStats();
- }
-
// Stops rendering by setting the sink of the renderer to nullptr. No data
// callback will be received after this method.
// This method is called on the libjingle worker thread.
void Stop() {
- RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
if (renderer_) {
renderer_->SetSink(nullptr);
renderer_ = nullptr;
@@ -1374,11 +1155,12 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
void OnData(const void* audio_data,
int bits_per_sample,
int sample_rate,
- int number_of_channels,
+ size_t number_of_channels,
size_t number_of_frames) override {
+ RTC_DCHECK(!worker_thread_checker_.CalledOnValidThread());
RTC_DCHECK(audio_capture_thread_checker_.CalledOnValidThread());
RTC_DCHECK(voe_audio_transport_);
- voe_audio_transport_->OnData(channel_,
+ voe_audio_transport_->OnData(config_.voe_channel_id,
audio_data,
bits_per_sample,
sample_rate,
@@ -1389,7 +1171,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
// Callback from the |renderer_| when it is going away. In case Start() has
// never been called, this callback won't be triggered.
void OnClose() override {
- RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
// Set |renderer_| to nullptr to make sure no more callback will get into
// the renderer.
renderer_ = nullptr;
@@ -1397,16 +1179,18 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
// Accessor to the VoE channel ID.
int channel() const {
- RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
- return channel_;
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ return config_.voe_channel_id;
}
private:
- rtc::ThreadChecker signal_thread_checker_;
+ rtc::ThreadChecker worker_thread_checker_;
rtc::ThreadChecker audio_capture_thread_checker_;
- const int channel_ = -1;
webrtc::AudioTransport* const voe_audio_transport_ = nullptr;
webrtc::Call* call_ = nullptr;
+ webrtc::AudioSendStream::Config config_;
+ // The stream is owned by WebRtcAudioSendStream and may be reallocated if
+ // configuration changes.
webrtc::AudioSendStream* stream_ = nullptr;
// Raw pointer to AudioRenderer owned by LocalAudioTrackHandler.
@@ -1419,80 +1203,163 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
public:
- explicit WebRtcAudioReceiveStream(int voe_channel_id)
- : channel_(voe_channel_id) {}
+ WebRtcAudioReceiveStream(int ch, uint32_t remote_ssrc, uint32_t local_ssrc,
+ bool use_combined_bwe, const std::string& sync_group,
+ const std::vector<webrtc::RtpExtension>& extensions,
+ webrtc::Call* call)
+ : call_(call),
+ config_() {
+ RTC_DCHECK_GE(ch, 0);
+ RTC_DCHECK(call);
+ config_.rtp.remote_ssrc = remote_ssrc;
+ config_.rtp.local_ssrc = local_ssrc;
+ config_.voe_channel_id = ch;
+ config_.sync_group = sync_group;
+ RecreateAudioReceiveStream(use_combined_bwe, extensions);
+ }
- int channel() { return channel_; }
+ ~WebRtcAudioReceiveStream() {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ call_->DestroyAudioReceiveStream(stream_);
+ }
+
+ void RecreateAudioReceiveStream(
+ const std::vector<webrtc::RtpExtension>& extensions) {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ RecreateAudioReceiveStream(config_.combined_audio_video_bwe, extensions);
+ }
+ void RecreateAudioReceiveStream(bool use_combined_bwe) {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ RecreateAudioReceiveStream(use_combined_bwe, config_.rtp.extensions);
+ }
+
+ webrtc::AudioReceiveStream::Stats GetStats() const {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(stream_);
+ return stream_->GetStats();
+ }
+
+ int channel() const {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ return config_.voe_channel_id;
+ }
+
+ void SetRawAudioSink(rtc::scoped_ptr<webrtc::AudioSinkInterface> sink) {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ stream_->SetSink(std::move(sink));
+ }
private:
- int channel_;
+ void RecreateAudioReceiveStream(bool use_combined_bwe,
+ const std::vector<webrtc::RtpExtension>& extensions) {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ if (stream_) {
+ call_->DestroyAudioReceiveStream(stream_);
+ stream_ = nullptr;
+ }
+ config_.rtp.extensions = extensions;
+ config_.combined_audio_video_bwe = use_combined_bwe;
+ RTC_DCHECK(!stream_);
+ stream_ = call_->CreateAudioReceiveStream(config_);
+ RTC_CHECK(stream_);
+ }
+
+ rtc::ThreadChecker worker_thread_checker_;
+ webrtc::Call* call_ = nullptr;
+ webrtc::AudioReceiveStream::Config config_;
+ // The stream is owned by WebRtcAudioReceiveStream and may be reallocated if
+ // configuration changes.
+ webrtc::AudioReceiveStream* stream_ = nullptr;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioReceiveStream);
};
-// WebRtcVoiceMediaChannel
WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine,
const AudioOptions& options,
webrtc::Call* call)
- : engine_(engine),
- send_bitrate_setting_(false),
- send_bitrate_bps_(0),
- options_(),
- dtmf_allowed_(false),
- desired_playout_(false),
- nack_enabled_(false),
- playout_(false),
- typing_noise_detected_(false),
- desired_send_(SEND_NOTHING),
- send_(SEND_NOTHING),
- call_(call) {
+ : engine_(engine), call_(call) {
LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel";
- RTC_DCHECK(nullptr != call);
+ RTC_DCHECK(call);
engine->RegisterChannel(this);
SetOptions(options);
}
WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel";
-
- // Remove any remaining send streams.
+ // TODO(solenberg): Should be able to delete the streams directly, without
+ // going through RemoveNnStream(), once stream objects handle
+ // all (de)configuration.
while (!send_streams_.empty()) {
RemoveSendStream(send_streams_.begin()->first);
}
-
- // Remove any remaining receive streams.
- while (!receive_channels_.empty()) {
- RemoveRecvStream(receive_channels_.begin()->first);
+ while (!recv_streams_.empty()) {
+ RemoveRecvStream(recv_streams_.begin()->first);
}
- RTC_DCHECK(receive_streams_.empty());
-
- // Unregister ourselves from the engine.
engine()->UnregisterChannel(this);
}
bool WebRtcVoiceMediaChannel::SetSendParameters(
const AudioSendParameters& params) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendParameters: "
+ << params.ToString();
// TODO(pthatcher): Refactor this to be more clean now that we have
// all the information at once.
- return (SetSendCodecs(params.codecs) &&
- SetSendRtpHeaderExtensions(params.extensions) &&
- SetMaxSendBandwidth(params.max_bandwidth_bps) &&
- SetOptions(params.options));
+
+ if (!SetSendCodecs(params.codecs)) {
+ return false;
+ }
+
+ if (!ValidateRtpExtensions(params.extensions)) {
+ return false;
+ }
+ std::vector<webrtc::RtpExtension> filtered_extensions =
+ FilterRtpExtensions(params.extensions,
+ webrtc::RtpExtension::IsSupportedForAudio, true);
+ if (send_rtp_extensions_ != filtered_extensions) {
+ send_rtp_extensions_.swap(filtered_extensions);
+ for (auto& it : send_streams_) {
+ it.second->RecreateAudioSendStream(send_rtp_extensions_);
+ }
+ }
+
+ if (!SetMaxSendBandwidth(params.max_bandwidth_bps)) {
+ return false;
+ }
+ return SetOptions(params.options);
}
bool WebRtcVoiceMediaChannel::SetRecvParameters(
const AudioRecvParameters& params) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetRecvParameters: "
+ << params.ToString();
// TODO(pthatcher): Refactor this to be more clean now that we have
// all the information at once.
- return (SetRecvCodecs(params.codecs) &&
- SetRecvRtpHeaderExtensions(params.extensions));
+
+ if (!SetRecvCodecs(params.codecs)) {
+ return false;
+ }
+
+ if (!ValidateRtpExtensions(params.extensions)) {
+ return false;
+ }
+ std::vector<webrtc::RtpExtension> filtered_extensions =
+ FilterRtpExtensions(params.extensions,
+ webrtc::RtpExtension::IsSupportedForAudio, false);
+ if (recv_rtp_extensions_ != filtered_extensions) {
+ recv_rtp_extensions_.swap(filtered_extensions);
+ for (auto& it : recv_streams_) {
+ it.second->RecreateAudioReceiveStream(recv_rtp_extensions_);
+ }
+ }
+
+ return true;
}
bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
LOG(LS_INFO) << "Setting voice channel options: "
<< options.ToString();
@@ -1503,26 +1370,27 @@ bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
// on top. This means there is no way to "clear" options such that
// they go back to the engine default.
options_.SetAll(options);
-
- if (send_ != SEND_NOTHING) {
- if (!engine()->ApplyOptions(options_)) {
- LOG(LS_WARNING) <<
- "Failed to apply engine options during channel SetOptions.";
- return false;
- }
+ if (!engine()->ApplyOptions(options_)) {
+ LOG(LS_WARNING) <<
+ "Failed to apply engine options during channel SetOptions.";
+ return false;
}
if (dscp_option_changed) {
rtc::DiffServCodePoint dscp = rtc::DSCP_DEFAULT;
- if (options_.dscp.GetWithDefaultIfUnset(false))
+ if (options_.dscp.value_or(false)) {
dscp = kAudioDscpValue;
+ }
if (MediaChannel::SetDscp(dscp) != 0) {
LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel";
}
}
// TODO(solenberg): Don't recreate unless options changed.
- RecreateAudioReceiveStreams();
+ for (auto& it : recv_streams_) {
+ it.second->RecreateAudioReceiveStream(
+ options_.combined_audio_video_bwe.value_or(false));
+ }
LOG(LS_INFO) << "Set voice channel options. Current options: "
<< options_.ToString();
@@ -1531,7 +1399,7 @@ bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
bool WebRtcVoiceMediaChannel::SetRecvCodecs(
const std::vector<AudioCodec>& codecs) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
// Set the payload types to be used for incoming media.
LOG(LS_INFO) << "Setting receive voice codecs.";
@@ -1568,7 +1436,26 @@ bool WebRtcVoiceMediaChannel::SetRecvCodecs(
PausePlayout();
}
- bool result = SetRecvCodecsInternal(new_codecs);
+ bool result = true;
+ for (const AudioCodec& codec : new_codecs) {
+ webrtc::CodecInst voe_codec;
+ if (WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) {
+ LOG(LS_INFO) << ToString(codec);
+ voe_codec.pltype = codec.id;
+ for (const auto& ch : recv_streams_) {
+ if (engine()->voe()->codec()->SetRecPayloadType(
+ ch.second->channel(), voe_codec) == -1) {
+ LOG_RTCERR2(SetRecPayloadType, ch.second->channel(),
+ ToString(voe_codec));
+ result = false;
+ }
+ }
+ } else {
+ LOG(LS_WARNING) << "Unknown codec " << ToString(codec);
+ result = false;
+ break;
+ }
+ }
if (result) {
recv_codecs_ = codecs;
}
@@ -1588,7 +1475,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
engine()->voe()->codec()->SetFECStatus(channel, false);
// Scan through the list to figure out the codec to use for sending, along
- // with the proper configuration for VAD and DTMF.
+ // with the proper configuration for VAD.
bool found_send_codec = false;
webrtc::CodecInst send_codec;
memset(&send_codec, 0, sizeof(send_codec));
@@ -1603,7 +1490,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
// Ignore codecs we don't know about. The negotiation step should prevent
// this, but double-check to be sure.
webrtc::CodecInst voe_codec;
- if (!engine()->FindWebRtcCodec(codec, &voe_codec)) {
+ if (!WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) {
LOG(LS_WARNING) << "Unknown codec " << ToString(codec);
continue;
}
@@ -1644,7 +1531,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
// Set packet size if the AudioCodec param kCodecParamPTime is set.
int ptime_ms = 0;
if (codec.GetParam(kCodecParamPTime, &ptime_ms)) {
- if (!SetPTimeAsPacketSize(&send_codec, ptime_ms)) {
+ if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize(&send_codec, ptime_ms)) {
LOG(LS_WARNING) << "Failed to set packet size for codec "
<< send_codec.plname;
return false;
@@ -1687,7 +1574,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
// Set Opus internal DTX.
LOG(LS_INFO) << "Attempt to "
- << GetEnableString(enable_opus_dtx)
+ << (enable_opus_dtx ? "enable" : "disable")
<< " Opus DTX on channel "
<< channel;
if (engine()->voe()->codec()->SetOpusDtx(channel, enable_opus_dtx)) {
@@ -1717,25 +1604,17 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
SetSendBitrateInternal(send_bitrate_bps_);
}
- // Loop through the codecs list again to config the telephone-event/CN codec.
+ // Loop through the codecs list again to config the CN codec.
for (const AudioCodec& codec : codecs) {
// Ignore codecs we don't know about. The negotiation step should prevent
// this, but double-check to be sure.
webrtc::CodecInst voe_codec;
- if (!engine()->FindWebRtcCodec(codec, &voe_codec)) {
+ if (!WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) {
LOG(LS_WARNING) << "Unknown codec " << ToString(codec);
continue;
}
- // Find the DTMF telephone event "codec" and tell VoiceEngine channels
- // about it.
- if (IsCodec(codec, kDtmfCodecName)) {
- if (engine()->voe()->dtmf()->SetSendTelephoneEventPayloadType(
- channel, codec.id) == -1) {
- LOG_RTCERR2(SetSendTelephoneEventPayloadType, channel, codec.id);
- return false;
- }
- } else if (IsCodec(codec, kCnCodecName)) {
+ if (IsCodec(codec, kCnCodecName)) {
// Turn voice activity detection/comfort noise on if supported.
// Set the wideband CN payload type appropriately.
// (narrowband always uses the static payload type 13).
@@ -1789,13 +1668,17 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
bool WebRtcVoiceMediaChannel::SetSendCodecs(
const std::vector<AudioCodec>& codecs) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ // TODO(solenberg): Validate input - that payload types don't overlap, are
+ // within range, filter out codecs we don't support,
+ // redundant codecs etc.
- dtmf_allowed_ = false;
+ // Find the DTMF telephone event "codec" payload type.
+ dtmf_payload_type_ = rtc::Optional<int>();
for (const AudioCodec& codec : codecs) {
- // Find the DTMF telephone event "codec".
if (IsCodec(codec, kDtmfCodecName)) {
- dtmf_allowed_ = true;
+ dtmf_payload_type_ = rtc::Optional<int>(codec.id);
+ break;
}
}
@@ -1808,7 +1691,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
}
// Set nack status on receive channels and update |nack_enabled_|.
- for (const auto& ch : receive_channels_) {
+ for (const auto& ch : recv_streams_) {
SetNack(ch.second->channel(), nack_enabled_);
}
@@ -1844,106 +1727,6 @@ bool WebRtcVoiceMediaChannel::SetSendCodec(
return true;
}
-bool WebRtcVoiceMediaChannel::SetRecvRtpHeaderExtensions(
- const std::vector<RtpHeaderExtension>& extensions) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
- if (receive_extensions_ == extensions) {
- return true;
- }
-
- for (const auto& ch : receive_channels_) {
- if (!SetChannelRecvRtpHeaderExtensions(ch.second->channel(), extensions)) {
- return false;
- }
- }
-
- receive_extensions_ = extensions;
-
- // Recreate AudioReceiveStream:s.
- {
- std::vector<webrtc::RtpExtension> exts;
-
- const RtpHeaderExtension* audio_level_extension =
- FindHeaderExtension(extensions, kRtpAudioLevelHeaderExtension);
- if (audio_level_extension) {
- exts.push_back({
- kRtpAudioLevelHeaderExtension, audio_level_extension->id});
- }
-
- const RtpHeaderExtension* send_time_extension =
- FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension);
- if (send_time_extension) {
- exts.push_back({
- kRtpAbsoluteSenderTimeHeaderExtension, send_time_extension->id});
- }
-
- recv_rtp_extensions_.swap(exts);
- RecreateAudioReceiveStreams();
- }
-
- return true;
-}
-
-bool WebRtcVoiceMediaChannel::SetChannelRecvRtpHeaderExtensions(
- int channel_id, const std::vector<RtpHeaderExtension>& extensions) {
- const RtpHeaderExtension* audio_level_extension =
- FindHeaderExtension(extensions, kRtpAudioLevelHeaderExtension);
- if (!SetHeaderExtension(
- &webrtc::VoERTP_RTCP::SetReceiveAudioLevelIndicationStatus, channel_id,
- audio_level_extension)) {
- return false;
- }
-
- const RtpHeaderExtension* send_time_extension =
- FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension);
- if (!SetHeaderExtension(
- &webrtc::VoERTP_RTCP::SetReceiveAbsoluteSenderTimeStatus, channel_id,
- send_time_extension)) {
- return false;
- }
-
- return true;
-}
-
-bool WebRtcVoiceMediaChannel::SetSendRtpHeaderExtensions(
- const std::vector<RtpHeaderExtension>& extensions) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
- if (send_extensions_ == extensions) {
- return true;
- }
-
- for (const auto& ch : send_streams_) {
- if (!SetChannelSendRtpHeaderExtensions(ch.second->channel(), extensions)) {
- return false;
- }
- }
-
- send_extensions_ = extensions;
- return true;
-}
-
-bool WebRtcVoiceMediaChannel::SetChannelSendRtpHeaderExtensions(
- int channel_id, const std::vector<RtpHeaderExtension>& extensions) {
- const RtpHeaderExtension* audio_level_extension =
- FindHeaderExtension(extensions, kRtpAudioLevelHeaderExtension);
-
- if (!SetHeaderExtension(
- &webrtc::VoERTP_RTCP::SetSendAudioLevelIndicationStatus, channel_id,
- audio_level_extension)) {
- return false;
- }
-
- const RtpHeaderExtension* send_time_extension =
- FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension);
- if (!SetHeaderExtension(
- &webrtc::VoERTP_RTCP::SetSendAbsoluteSenderTimeStatus, channel_id,
- send_time_extension)) {
- return false;
- }
-
- return true;
-}
-
bool WebRtcVoiceMediaChannel::SetPlayout(bool playout) {
desired_playout_ = playout;
return ChangePlayout(desired_playout_);
@@ -1958,12 +1741,12 @@ bool WebRtcVoiceMediaChannel::ResumePlayout() {
}
bool WebRtcVoiceMediaChannel::ChangePlayout(bool playout) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
if (playout_ == playout) {
return true;
}
- for (const auto& ch : receive_channels_) {
+ for (const auto& ch : recv_streams_) {
if (!SetPlayout(ch.second->channel(), playout)) {
LOG(LS_ERROR) << "SetPlayout " << playout << " on channel "
<< ch.second->channel() << " failed";
@@ -1995,7 +1778,7 @@ bool WebRtcVoiceMediaChannel::ChangeSend(SendFlags send) {
return true;
}
- // Apply channel specific options.
+ // Apply channel specific options when channel is enabled for sending.
if (send == SEND_MICROPHONE) {
engine()->ApplyOptions(options_);
}
@@ -2007,13 +1790,6 @@ bool WebRtcVoiceMediaChannel::ChangeSend(SendFlags send) {
}
}
- // Clear up the options after stopping sending. Since we may previously have
- // applied the channel specific options, now apply the original options stored
- // in WebRtcVoiceEngine.
- if (send == SEND_NOTHING) {
- engine()->ApplyOptions(engine()->GetOptions());
- }
-
send_ = send;
return true;
}
@@ -2039,7 +1815,7 @@ bool WebRtcVoiceMediaChannel::SetAudioSend(uint32_t ssrc,
bool enable,
const AudioOptions* options,
AudioRenderer* renderer) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
// TODO(solenberg): The state change should be fully rolled back if any one of
// these calls fail.
if (!SetLocalRenderer(ssrc, renderer)) {
@@ -2068,7 +1844,7 @@ int WebRtcVoiceMediaChannel::CreateVoEChannel() {
return id;
}
-bool WebRtcVoiceMediaChannel::DeleteChannel(int channel) {
+bool WebRtcVoiceMediaChannel::DeleteVoEChannel(int channel) {
if (engine()->voe()->network()->DeRegisterExternalTransport(channel) == -1) {
LOG_RTCERR1(DeRegisterExternalTransport, channel);
}
@@ -2080,7 +1856,7 @@ bool WebRtcVoiceMediaChannel::DeleteChannel(int channel) {
}
bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
LOG(LS_INFO) << "AddSendStream: " << sp.ToString();
uint32_t ssrc = sp.first_ssrc();
@@ -2097,33 +1873,12 @@ bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
return false;
}
- // Enable RTCP (for quality stats and feedback messages).
- if (engine()->voe()->rtp()->SetRTCPStatus(channel, true) == -1) {
- LOG_RTCERR2(SetRTCPStatus, channel, 1);
- }
-
- SetChannelSendRtpHeaderExtensions(channel, send_extensions_);
-
- // Set the local (send) SSRC.
- if (engine()->voe()->rtp()->SetLocalSSRC(channel, ssrc) == -1) {
- LOG_RTCERR2(SetLocalSSRC, channel, ssrc);
- DeleteChannel(channel);
- return false;
- }
-
- if (engine()->voe()->rtp()->SetRTCP_CNAME(channel, sp.cname.c_str()) == -1) {
- LOG_RTCERR2(SetRTCP_CNAME, channel, sp.cname);
- DeleteChannel(channel);
- return false;
- }
-
// Save the channel to send_streams_, so that RemoveSendStream() can still
// delete the channel in case failure happens below.
webrtc::AudioTransport* audio_transport =
engine()->voe()->base()->audio_transport();
- send_streams_.insert(
- std::make_pair(ssrc,
- new WebRtcAudioSendStream(channel, audio_transport, ssrc, call_)));
+ send_streams_.insert(std::make_pair(ssrc, new WebRtcAudioSendStream(
+ channel, audio_transport, ssrc, sp.cname, send_rtp_extensions_, call_)));
// Set the current codecs to be used for the new channel. We need to do this
// after adding the channel to send_channels_, because of how max bitrate is
@@ -2138,10 +1893,10 @@ bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
// with the same SSRC in order to send receiver reports.
if (send_streams_.size() == 1) {
receiver_reports_ssrc_ = ssrc;
- for (const auto& ch : receive_channels_) {
- int recv_channel = ch.second->channel();
+ for (const auto& stream : recv_streams_) {
+ int recv_channel = stream.second->channel();
if (engine()->voe()->rtp()->SetLocalSSRC(recv_channel, ssrc) != 0) {
- LOG_RTCERR2(SetLocalSSRC, ch.second->channel(), ssrc);
+ LOG_RTCERR2(SetLocalSSRC, recv_channel, ssrc);
return false;
}
engine()->voe()->base()->AssociateSendChannel(recv_channel, channel);
@@ -2154,7 +1909,9 @@ bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
}
bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ LOG(LS_INFO) << "RemoveSendStream: " << ssrc;
+
auto it = send_streams_.find(ssrc);
if (it == send_streams_.end()) {
LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
@@ -2165,15 +1922,12 @@ bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) {
int channel = it->second->channel();
ChangeSend(channel, SEND_NOTHING);
- // Delete the WebRtcVoiceChannelRenderer object connected to the channel,
- // this will disconnect the audio renderer with the send channel.
- delete it->second;
- send_streams_.erase(it);
-
- // Clean up and delete the send channel.
+ // Clean up and delete the send stream+channel.
LOG(LS_INFO) << "Removing audio send stream " << ssrc
<< " with VoiceEngine channel #" << channel << ".";
- if (!DeleteChannel(channel)) {
+ delete it->second;
+ send_streams_.erase(it);
+ if (!DeleteVoEChannel(channel)) {
return false;
}
if (send_streams_.empty()) {
@@ -2183,14 +1937,14 @@ bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) {
}
bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
LOG(LS_INFO) << "AddRecvStream: " << sp.ToString();
if (!ValidateStreamParams(sp)) {
return false;
}
- uint32_t ssrc = sp.first_ssrc();
+ const uint32_t ssrc = sp.first_ssrc();
if (ssrc == 0) {
LOG(LS_WARNING) << "AddRecvStream with ssrc==0 is not supported.";
return false;
@@ -2202,114 +1956,87 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
RemoveRecvStream(ssrc);
}
- if (receive_channels_.find(ssrc) != receive_channels_.end()) {
+ if (GetReceiveChannelId(ssrc) != -1) {
LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
return false;
}
- RTC_DCHECK(receive_stream_params_.find(ssrc) == receive_stream_params_.end());
// Create a new channel for receiving audio data.
- int channel = CreateVoEChannel();
+ const int channel = CreateVoEChannel();
if (channel == -1) {
return false;
}
- if (!ConfigureRecvChannel(channel)) {
- DeleteChannel(channel);
- return false;
- }
-
- WebRtcAudioReceiveStream* stream = new WebRtcAudioReceiveStream(channel);
- receive_channels_.insert(std::make_pair(ssrc, stream));
- receive_stream_params_[ssrc] = sp;
- AddAudioReceiveStream(ssrc);
-
- LOG(LS_INFO) << "New audio stream " << ssrc
- << " registered to VoiceEngine channel #"
- << channel << ".";
- return true;
-}
-
-bool WebRtcVoiceMediaChannel::ConfigureRecvChannel(int channel) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
-
- int send_channel = GetSendChannelId(receiver_reports_ssrc_);
- if (send_channel != -1) {
- // Associate receive channel with first send channel (so the receive channel
- // can obtain RTT from the send channel)
- engine()->voe()->base()->AssociateSendChannel(channel, send_channel);
- LOG(LS_INFO) << "VoiceEngine channel #" << channel
- << " is associated with channel #" << send_channel << ".";
- }
- if (engine()->voe()->rtp()->SetLocalSSRC(channel,
- receiver_reports_ssrc_) == -1) {
- LOG_RTCERR1(SetLocalSSRC, channel);
- return false;
- }
// Turn off all supported codecs.
- int ncodecs = engine()->voe()->codec()->NumOfCodecs();
- for (int i = 0; i < ncodecs; ++i) {
- webrtc::CodecInst voe_codec;
- if (engine()->voe()->codec()->GetCodec(i, voe_codec) != -1) {
- voe_codec.pltype = -1;
- if (engine()->voe()->codec()->SetRecPayloadType(
- channel, voe_codec) == -1) {
- LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec));
- return false;
- }
+ // TODO(solenberg): Remove once "no codecs" is the default state of a stream.
+ for (webrtc::CodecInst voe_codec : webrtc::acm2::RentACodec::Database()) {
+ voe_codec.pltype = -1;
+ if (engine()->voe()->codec()->SetRecPayloadType(channel, voe_codec) == -1) {
+ LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec));
+ DeleteVoEChannel(channel);
+ return false;
}
}
// Only enable those configured for this channel.
for (const auto& codec : recv_codecs_) {
webrtc::CodecInst voe_codec;
- if (engine()->FindWebRtcCodec(codec, &voe_codec)) {
+ if (WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) {
voe_codec.pltype = codec.id;
if (engine()->voe()->codec()->SetRecPayloadType(
channel, voe_codec) == -1) {
LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec));
+ DeleteVoEChannel(channel);
return false;
}
}
}
- SetNack(channel, nack_enabled_);
-
- // Set RTP header extension for the new channel.
- if (!SetChannelRecvRtpHeaderExtensions(channel, receive_extensions_)) {
- return false;
+ const int send_channel = GetSendChannelId(receiver_reports_ssrc_);
+ if (send_channel != -1) {
+ // Associate receive channel with first send channel (so the receive channel
+ // can obtain RTT from the send channel)
+ engine()->voe()->base()->AssociateSendChannel(channel, send_channel);
+ LOG(LS_INFO) << "VoiceEngine channel #" << channel
+ << " is associated with channel #" << send_channel << ".";
}
+ recv_streams_.insert(std::make_pair(ssrc, new WebRtcAudioReceiveStream(
+ channel, ssrc, receiver_reports_ssrc_,
+ options_.combined_audio_video_bwe.value_or(false), sp.sync_label,
+ recv_rtp_extensions_, call_)));
+
+ SetNack(channel, nack_enabled_);
SetPlayout(channel, playout_);
+
return true;
}
bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
- auto it = receive_channels_.find(ssrc);
- if (it == receive_channels_.end()) {
+ const auto it = recv_streams_.find(ssrc);
+ if (it == recv_streams_.end()) {
LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
<< " which doesn't exist.";
return false;
}
- RemoveAudioReceiveStream(ssrc);
- receive_stream_params_.erase(ssrc);
-
- const int channel = it->second->channel();
- delete it->second;
- receive_channels_.erase(it);
-
// Deregister default channel, if that's the one being destroyed.
if (IsDefaultRecvStream(ssrc)) {
default_recv_ssrc_ = -1;
}
- LOG(LS_INFO) << "Removing audio stream " << ssrc
+ const int channel = it->second->channel();
+
+ // Clean up and delete the receive stream+channel.
+ LOG(LS_INFO) << "Removing audio receive stream " << ssrc
<< " with VoiceEngine channel #" << channel << ".";
- return DeleteChannel(channel);
+ it->second->SetRawAudioSink(nullptr);
+ delete it->second;
+ recv_streams_.erase(it);
+ return DeleteVoEChannel(channel);
}
bool WebRtcVoiceMediaChannel::SetLocalRenderer(uint32_t ssrc,
@@ -2337,9 +2064,9 @@ bool WebRtcVoiceMediaChannel::SetLocalRenderer(uint32_t ssrc,
bool WebRtcVoiceMediaChannel::GetActiveStreams(
AudioInfo::StreamList* actives) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
actives->clear();
- for (const auto& ch : receive_channels_) {
+ for (const auto& ch : recv_streams_) {
int level = GetOutputLevel(ch.second->channel());
if (level > 0) {
actives->push_back(std::make_pair(ch.first, level));
@@ -2349,9 +2076,9 @@ bool WebRtcVoiceMediaChannel::GetActiveStreams(
}
int WebRtcVoiceMediaChannel::GetOutputLevel() {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
int highest = 0;
- for (const auto& ch : receive_channels_) {
+ for (const auto& ch : recv_streams_) {
highest = std::max(GetOutputLevel(ch.second->channel()), highest);
}
return highest;
@@ -2383,7 +2110,7 @@ void WebRtcVoiceMediaChannel::SetTypingDetectionParameters(int time_window,
}
bool WebRtcVoiceMediaChannel::SetOutputVolume(uint32_t ssrc, double volume) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
if (ssrc == 0) {
default_recv_volume_ = volume;
if (default_recv_ssrc_ == -1) {
@@ -2408,64 +2135,48 @@ bool WebRtcVoiceMediaChannel::SetOutputVolume(uint32_t ssrc, double volume) {
}
bool WebRtcVoiceMediaChannel::CanInsertDtmf() {
- return dtmf_allowed_;
+ return dtmf_payload_type_ ? true : false;
}
-bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc,
- int event,
- int duration,
- int flags) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
- if (!dtmf_allowed_) {
+bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc, int event,
+ int duration) {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ LOG(LS_INFO) << "WebRtcVoiceMediaChannel::InsertDtmf";
+ if (!dtmf_payload_type_) {
return false;
}
- // Send the event.
- if (flags & cricket::DF_SEND) {
- int channel = -1;
- if (ssrc == 0) {
- if (send_streams_.size() > 0) {
- channel = send_streams_.begin()->second->channel();
- }
- } else {
- channel = GetSendChannelId(ssrc);
- }
- if (channel == -1) {
- LOG(LS_WARNING) << "InsertDtmf - The specified ssrc "
- << ssrc << " is not in use.";
- return false;
- }
- // Send DTMF using out-of-band DTMF. ("true", as 3rd arg)
- if (engine()->voe()->dtmf()->SendTelephoneEvent(
- channel, event, true, duration) == -1) {
- LOG_RTCERR4(SendTelephoneEvent, channel, event, true, duration);
- return false;
- }
+ // Figure out which WebRtcAudioSendStream to send the event on.
+ auto it = ssrc != 0 ? send_streams_.find(ssrc) : send_streams_.begin();
+ if (it == send_streams_.end()) {
+ LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
+ return false;
}
-
- // Play the event.
- if (flags & cricket::DF_PLAY) {
- // Play DTMF tone locally.
- if (engine()->voe()->dtmf()->PlayDtmfTone(event, duration) == -1) {
- LOG_RTCERR2(PlayDtmfTone, event, duration);
- return false;
- }
+ if (event < kMinTelephoneEventCode ||
+ event > kMaxTelephoneEventCode) {
+ LOG(LS_WARNING) << "DTMF event code " << event << " out of range.";
+ return false;
}
-
- return true;
+ if (duration < kMinTelephoneEventDuration ||
+ duration > kMaxTelephoneEventDuration) {
+ LOG(LS_WARNING) << "DTMF event duration " << duration << " out of range.";
+ return false;
+ }
+ return it->second->SendTelephoneEvent(*dtmf_payload_type_, event, duration);
}
void WebRtcVoiceMediaChannel::OnPacketReceived(
rtc::Buffer* packet, const rtc::PacketTime& packet_time) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
uint32_t ssrc = 0;
if (!GetRtpSsrc(packet->data(), packet->size(), &ssrc)) {
return;
}
- if (receive_channels_.empty()) {
- // Create new channel, which will be the default receive channel.
+ // If we don't have a default channel, and the SSRC is unknown, create a
+ // default channel.
+ if (default_recv_ssrc_ == -1 && GetReceiveChannelId(ssrc) == -1) {
StreamParams sp;
sp.ssrcs.push_back(ssrc);
LOG(LS_INFO) << "Creating default receive stream for SSRC=" << ssrc << ".";
@@ -2485,7 +2196,13 @@ void WebRtcVoiceMediaChannel::OnPacketReceived(
reinterpret_cast<const uint8_t*>(packet->data()), packet->size(),
webrtc_packet_time);
if (webrtc::PacketReceiver::DELIVERY_OK != delivery_result) {
- return;
+ // If the SSRC is unknown here, route it to the default channel, if we have
+ // one. See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5208
+ if (default_recv_ssrc_ == -1) {
+ return;
+ } else {
+ ssrc = default_recv_ssrc_;
+ }
}
// Find the channel to send this packet to. It must exist since webrtc::Call
@@ -2500,7 +2217,7 @@ void WebRtcVoiceMediaChannel::OnPacketReceived(
void WebRtcVoiceMediaChannel::OnRtcpReceived(
rtc::Buffer* packet, const rtc::PacketTime& packet_time) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
// Forward packet to Call as well.
const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
@@ -2542,7 +2259,7 @@ void WebRtcVoiceMediaChannel::OnRtcpReceived(
}
bool WebRtcVoiceMediaChannel::MuteStream(uint32_t ssrc, bool muted) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
int channel = GetSendChannelId(ssrc);
if (channel == -1) {
LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
@@ -2601,7 +2318,7 @@ bool WebRtcVoiceMediaChannel::SetSendBitrateInternal(int bps) {
return true;
webrtc::CodecInst codec = *send_codec_;
- bool is_multi_rate = IsCodecMultiRate(codec);
+ bool is_multi_rate = WebRtcVoiceCodecs::IsCodecMultiRate(codec);
if (is_multi_rate) {
// If codec is multi-rate then just set the bitrate.
@@ -2629,7 +2346,7 @@ bool WebRtcVoiceMediaChannel::SetSendBitrateInternal(int bps) {
}
bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
RTC_DCHECK(info);
// Get SSRC and stats for each sender.
@@ -2652,15 +2369,14 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
sinfo.echo_delay_std_ms = stats.echo_delay_std_ms;
sinfo.echo_return_loss = stats.echo_return_loss;
sinfo.echo_return_loss_enhancement = stats.echo_return_loss_enhancement;
- sinfo.typing_noise_detected = typing_noise_detected_;
- // TODO(solenberg): Move to AudioSendStream.
- // sinfo.typing_noise_detected = stats.typing_noise_detected;
+ sinfo.typing_noise_detected =
+ (send_ == SEND_NOTHING ? false : stats.typing_noise_detected);
info->senders.push_back(sinfo);
}
// Get SSRC and stats for each receiver.
RTC_DCHECK(info->receivers.size() == 0);
- for (const auto& stream : receive_streams_) {
+ for (const auto& stream : recv_streams_) {
webrtc::AudioReceiveStream::Stats stats = stream.second->GetStats();
VoiceReceiverInfo rinfo;
rinfo.add_ssrc(stats.remote_ssrc);
@@ -2694,15 +2410,17 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
return true;
}
-void WebRtcVoiceMediaChannel::OnError(int error) {
- if (send_ == SEND_NOTHING) {
+void WebRtcVoiceMediaChannel::SetRawAudioSink(
+ uint32_t ssrc,
+ rtc::scoped_ptr<webrtc::AudioSinkInterface> sink) {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::SetRawAudioSink";
+ const auto it = recv_streams_.find(ssrc);
+ if (it == recv_streams_.end()) {
+ LOG(LS_WARNING) << "SetRawAudioSink: no recv stream" << ssrc;
return;
}
- if (error == VE_TYPING_NOISE_WARNING) {
- typing_noise_detected_ = true;
- } else if (error == VE_TYPING_NOISE_OFF_WARNING) {
- typing_noise_detected_ = false;
- }
+ it->second->SetRawAudioSink(std::move(sink));
}
int WebRtcVoiceMediaChannel::GetOutputLevel(int channel) {
@@ -2712,16 +2430,16 @@ int WebRtcVoiceMediaChannel::GetOutputLevel(int channel) {
}
int WebRtcVoiceMediaChannel::GetReceiveChannelId(uint32_t ssrc) const {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
- const auto it = receive_channels_.find(ssrc);
- if (it != receive_channels_.end()) {
+ 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(thread_checker_.CalledOnValidThread());
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
const auto it = send_streams_.find(ssrc);
if (it != send_streams_.end()) {
return it->second->channel();
@@ -2762,7 +2480,7 @@ bool WebRtcVoiceMediaChannel::GetRedSendCodec(const AudioCodec& red_codec,
if (codec.id == red_pt) {
// If we find the right codec, that will be the codec we pass to
// SetSendCodec, with the desired payload type.
- if (engine()->FindWebRtcCodec(codec, send_codec)) {
+ if (WebRtcVoiceEngine::ToCodecInst(codec, send_codec)) {
return true;
} else {
break;
@@ -2786,117 +2504,6 @@ bool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) {
}
return true;
}
-
-// Convert VoiceEngine error code into VoiceMediaChannel::Error enum.
-VoiceMediaChannel::Error
- WebRtcVoiceMediaChannel::WebRtcErrorToChannelError(int err_code) {
- switch (err_code) {
- case 0:
- return ERROR_NONE;
- case VE_CANNOT_START_RECORDING:
- case VE_MIC_VOL_ERROR:
- case VE_GET_MIC_VOL_ERROR:
- case VE_CANNOT_ACCESS_MIC_VOL:
- return ERROR_REC_DEVICE_OPEN_FAILED;
- case VE_SATURATION_WARNING:
- return ERROR_REC_DEVICE_SATURATION;
- case VE_REC_DEVICE_REMOVED:
- return ERROR_REC_DEVICE_REMOVED;
- case VE_RUNTIME_REC_WARNING:
- case VE_RUNTIME_REC_ERROR:
- return ERROR_REC_RUNTIME_ERROR;
- case VE_CANNOT_START_PLAYOUT:
- case VE_SPEAKER_VOL_ERROR:
- case VE_GET_SPEAKER_VOL_ERROR:
- case VE_CANNOT_ACCESS_SPEAKER_VOL:
- return ERROR_PLAY_DEVICE_OPEN_FAILED;
- case VE_RUNTIME_PLAY_WARNING:
- case VE_RUNTIME_PLAY_ERROR:
- return ERROR_PLAY_RUNTIME_ERROR;
- case VE_TYPING_NOISE_WARNING:
- return ERROR_REC_TYPING_NOISE_DETECTED;
- default:
- return VoiceMediaChannel::ERROR_OTHER;
- }
-}
-
-bool WebRtcVoiceMediaChannel::SetHeaderExtension(ExtensionSetterFunction setter,
- int channel_id, const RtpHeaderExtension* extension) {
- bool enable = false;
- int id = 0;
- std::string uri;
- if (extension) {
- enable = true;
- id = extension->id;
- uri = extension->uri;
- }
- if ((engine()->voe()->rtp()->*setter)(channel_id, enable, id) != 0) {
- LOG_RTCERR4(*setter, uri, channel_id, enable, id);
- return false;
- }
- return true;
-}
-
-void WebRtcVoiceMediaChannel::RecreateAudioReceiveStreams() {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
- for (const auto& it : receive_channels_) {
- RemoveAudioReceiveStream(it.first);
- }
- for (const auto& it : receive_channels_) {
- AddAudioReceiveStream(it.first);
- }
-}
-
-void WebRtcVoiceMediaChannel::AddAudioReceiveStream(uint32_t ssrc) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
- WebRtcAudioReceiveStream* stream = receive_channels_[ssrc];
- RTC_DCHECK(stream != nullptr);
- RTC_DCHECK(receive_streams_.find(ssrc) == receive_streams_.end());
- webrtc::AudioReceiveStream::Config config;
- config.rtp.remote_ssrc = ssrc;
- // Only add RTP extensions if we support combined A/V BWE.
- config.rtp.extensions = recv_rtp_extensions_;
- config.combined_audio_video_bwe =
- options_.combined_audio_video_bwe.GetWithDefaultIfUnset(false);
- config.voe_channel_id = stream->channel();
- config.sync_group = receive_stream_params_[ssrc].sync_label;
- webrtc::AudioReceiveStream* s = call_->CreateAudioReceiveStream(config);
- receive_streams_.insert(std::make_pair(ssrc, s));
-}
-
-void WebRtcVoiceMediaChannel::RemoveAudioReceiveStream(uint32_t ssrc) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
- auto stream_it = receive_streams_.find(ssrc);
- if (stream_it != receive_streams_.end()) {
- call_->DestroyAudioReceiveStream(stream_it->second);
- receive_streams_.erase(stream_it);
- }
-}
-
-bool WebRtcVoiceMediaChannel::SetRecvCodecsInternal(
- const std::vector<AudioCodec>& new_codecs) {
- RTC_DCHECK(thread_checker_.CalledOnValidThread());
- for (const AudioCodec& codec : new_codecs) {
- webrtc::CodecInst voe_codec;
- if (engine()->FindWebRtcCodec(codec, &voe_codec)) {
- LOG(LS_INFO) << ToString(codec);
- voe_codec.pltype = codec.id;
- for (const auto& ch : receive_channels_) {
- if (engine()->voe()->codec()->SetRecPayloadType(
- ch.second->channel(), voe_codec) == -1) {
- LOG_RTCERR2(SetRecPayloadType, ch.second->channel(),
- ToString(voe_codec));
- return false;
- }
- }
- } else {
- LOG(LS_WARNING) << "Unknown codec " << ToString(codec);
- return false;
- }
- }
- return true;
-}
-
} // namespace cricket
#endif // HAVE_WEBRTC_VOICE
diff --git a/talk/media/webrtc/webrtcvoiceengine.h b/talk/media/webrtc/webrtcvoiceengine.h
index 1cf05e71a2..0f2f59e492 100644
--- a/talk/media/webrtc/webrtcvoiceengine.h
+++ b/talk/media/webrtc/webrtcvoiceengine.h
@@ -29,7 +29,6 @@
#define TALK_MEDIA_WEBRTCVOICEENGINE_H_
#include <map>
-#include <set>
#include <string>
#include <vector>
@@ -37,9 +36,8 @@
#include "talk/media/webrtc/webrtccommon.h"
#include "talk/media/webrtc/webrtcvoe.h"
#include "talk/session/media/channel.h"
+#include "webrtc/audio_state.h"
#include "webrtc/base/buffer.h"
-#include "webrtc/base/byteorder.h"
-#include "webrtc/base/logging.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/stream.h"
#include "webrtc/base/thread_checker.h"
@@ -51,43 +49,34 @@ namespace cricket {
class AudioDeviceModule;
class AudioRenderer;
-class VoETraceWrapper;
class VoEWrapper;
class WebRtcVoiceMediaChannel;
// WebRtcVoiceEngine is a class to be used with CompositeMediaEngine.
// It uses the WebRtc VoiceEngine library for audio handling.
-class WebRtcVoiceEngine
- : public webrtc::VoiceEngineObserver,
- public webrtc::TraceCallback {
+class WebRtcVoiceEngine final : public webrtc::TraceCallback {
friend class WebRtcVoiceMediaChannel;
-
public:
+ // Exposed for the WVoE/MC unit test.
+ static bool ToCodecInst(const AudioCodec& in, webrtc::CodecInst* out);
+
WebRtcVoiceEngine();
// Dependency injection for testing.
- WebRtcVoiceEngine(VoEWrapper* voe_wrapper, VoETraceWrapper* tracing);
+ explicit WebRtcVoiceEngine(VoEWrapper* voe_wrapper);
~WebRtcVoiceEngine();
bool Init(rtc::Thread* worker_thread);
void Terminate();
- webrtc::VoiceEngine* GetVoE() { return voe()->engine(); }
+ rtc::scoped_refptr<webrtc::AudioState> GetAudioState() const;
VoiceMediaChannel* CreateChannel(webrtc::Call* call,
const AudioOptions& options);
- AudioOptions GetOptions() const { return options_; }
- bool SetOptions(const AudioOptions& options);
- bool SetDevices(const Device* in_device, const Device* out_device);
bool GetOutputVolume(int* level);
bool SetOutputVolume(int level);
int GetInputLevel();
const std::vector<AudioCodec>& codecs();
- bool FindCodec(const AudioCodec& codec);
- bool FindWebRtcCodec(const AudioCodec& codec, webrtc::CodecInst* gcodec);
-
- const std::vector<RtpHeaderExtension>& rtp_header_extensions() const;
-
- void SetLogging(int min_sev, const char* filter);
+ RtpCapabilities GetCapabilities() const;
// For tracking WebRtc channels. Needed because we have to pause them
// all when switching devices.
@@ -120,68 +109,49 @@ class WebRtcVoiceEngine
private:
void Construct();
- void ConstructCodecs();
- bool GetVoeCodec(int index, webrtc::CodecInst* codec);
bool InitInternal();
- void SetTraceFilter(int filter);
- void SetTraceOptions(const std::string& options);
// Every option that is "set" will be applied. Every option not "set" will be
// ignored. This allows us to selectively turn on and off different options
// easily at any time.
bool ApplyOptions(const AudioOptions& options);
+ void SetDefaultDevices();
// webrtc::TraceCallback:
void Print(webrtc::TraceLevel level, const char* trace, int length) override;
- // webrtc::VoiceEngineObserver:
- void CallbackOnError(int channel_id, int errCode) override;
-
- // Given the device type, name, and id, find device id. Return true and
- // set the output parameter rtc_id if successful.
- bool FindWebRtcAudioDeviceId(
- bool is_input, const std::string& dev_name, int dev_id, int* rtc_id);
-
void StartAecDump(const std::string& filename);
int CreateVoEChannel();
- static const int kDefaultLogSeverity = rtc::LS_WARNING;
+ rtc::ThreadChecker signal_thread_checker_;
+ rtc::ThreadChecker worker_thread_checker_;
// The primary instance of WebRtc VoiceEngine.
rtc::scoped_ptr<VoEWrapper> voe_wrapper_;
- rtc::scoped_ptr<VoETraceWrapper> tracing_;
+ rtc::scoped_refptr<webrtc::AudioState> audio_state_;
// The external audio device manager
- webrtc::AudioDeviceModule* adm_;
- int log_filter_;
- std::string log_options_;
- bool is_dumping_aec_;
+ webrtc::AudioDeviceModule* adm_ = nullptr;
std::vector<AudioCodec> codecs_;
- std::vector<RtpHeaderExtension> rtp_header_extensions_;
std::vector<WebRtcVoiceMediaChannel*> channels_;
- // channels_ can be read from WebRtc callback thread. We need a lock on that
- // callback as well as the RegisterChannel/UnregisterChannel.
- rtc::CriticalSection channels_cs_;
- webrtc::AgcConfig default_agc_config_;
-
webrtc::Config voe_config_;
+ bool initialized_ = false;
+ bool is_dumping_aec_ = false;
- bool initialized_;
- AudioOptions options_;
-
+ webrtc::AgcConfig default_agc_config_;
// Cache received extended_filter_aec, delay_agnostic_aec and experimental_ns
// values, and apply them in case they are missing in the audio options. We
// need to do this because SetExtraOptions() will revert to defaults for
// options which are not provided.
- Settable<bool> extended_filter_aec_;
- Settable<bool> delay_agnostic_aec_;
- Settable<bool> experimental_ns_;
+ rtc::Optional<bool> extended_filter_aec_;
+ rtc::Optional<bool> delay_agnostic_aec_;
+ rtc::Optional<bool> experimental_ns_;
RTC_DISALLOW_COPY_AND_ASSIGN(WebRtcVoiceEngine);
};
// WebRtcVoiceMediaChannel is an implementation of VoiceMediaChannel that uses
// WebRtc Voice Engine.
-class WebRtcVoiceMediaChannel : public VoiceMediaChannel,
- public webrtc::Transport {
+class WebRtcVoiceMediaChannel final : public VoiceMediaChannel,
+ public webrtc::Transport {
public:
WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine,
const AudioOptions& options,
@@ -217,7 +187,7 @@ class WebRtcVoiceMediaChannel : public VoiceMediaChannel,
bool SetOutputVolume(uint32_t ssrc, double volume) override;
bool CanInsertDtmf() override;
- bool InsertDtmf(uint32_t ssrc, int event, int duration, int flags) override;
+ bool InsertDtmf(uint32_t ssrc, int event, int duration) override;
void OnPacketReceived(rtc::Buffer* packet,
const rtc::PacketTime& packet_time) override;
@@ -226,6 +196,10 @@ class WebRtcVoiceMediaChannel : public VoiceMediaChannel,
void OnReadyToSend(bool ready) override {}
bool GetStats(VoiceMediaInfo* info) override;
+ void SetRawAudioSink(
+ uint32_t ssrc,
+ rtc::scoped_ptr<webrtc::AudioSinkInterface> sink) override;
+
// implements Transport interface
bool SendRtp(const uint8_t* data,
size_t len,
@@ -243,20 +217,14 @@ class WebRtcVoiceMediaChannel : public VoiceMediaChannel,
return VoiceMediaChannel::SendRtcp(&packet, rtc::PacketOptions());
}
- void OnError(int error);
-
int GetReceiveChannelId(uint32_t ssrc) const;
int GetSendChannelId(uint32_t ssrc) const;
private:
bool SetSendCodecs(const std::vector<AudioCodec>& codecs);
- bool SetSendRtpHeaderExtensions(
- const std::vector<RtpHeaderExtension>& extensions);
bool SetOptions(const AudioOptions& options);
bool SetMaxSendBandwidth(int bps);
bool SetRecvCodecs(const std::vector<AudioCodec>& codecs);
- bool SetRecvRtpHeaderExtensions(
- const std::vector<RtpHeaderExtension>& extensions);
bool SetLocalRenderer(uint32_t ssrc, AudioRenderer* renderer);
bool MuteStream(uint32_t ssrc, bool mute);
@@ -267,82 +235,55 @@ class WebRtcVoiceMediaChannel : public VoiceMediaChannel,
const std::vector<AudioCodec>& all_codecs,
webrtc::CodecInst* send_codec);
bool SetPlayout(int channel, bool playout);
- static Error WebRtcErrorToChannelError(int err_code);
-
- typedef int (webrtc::VoERTP_RTCP::* ExtensionSetterFunction)(int, bool,
- unsigned char);
-
void SetNack(int channel, bool nack_enabled);
bool SetSendCodec(int channel, const webrtc::CodecInst& send_codec);
bool ChangePlayout(bool playout);
bool ChangeSend(SendFlags send);
bool ChangeSend(int channel, SendFlags send);
- bool ConfigureRecvChannel(int channel);
int CreateVoEChannel();
- bool DeleteChannel(int channel);
+ bool DeleteVoEChannel(int channel);
bool IsDefaultRecvStream(uint32_t ssrc) {
return default_recv_ssrc_ == static_cast<int64_t>(ssrc);
}
bool SetSendCodecs(int channel, const std::vector<AudioCodec>& codecs);
bool SetSendBitrateInternal(int bps);
- bool SetHeaderExtension(ExtensionSetterFunction setter, int channel_id,
- const RtpHeaderExtension* extension);
- void RecreateAudioReceiveStreams();
- void AddAudioReceiveStream(uint32_t ssrc);
- void RemoveAudioReceiveStream(uint32_t ssrc);
- bool SetRecvCodecsInternal(const std::vector<AudioCodec>& new_codecs);
-
- bool SetChannelRecvRtpHeaderExtensions(
- int channel_id,
- const std::vector<RtpHeaderExtension>& extensions);
- bool SetChannelSendRtpHeaderExtensions(
- int channel_id,
- const std::vector<RtpHeaderExtension>& extensions);
+ rtc::ThreadChecker worker_thread_checker_;
- rtc::ThreadChecker thread_checker_;
-
- WebRtcVoiceEngine* const engine_;
+ WebRtcVoiceEngine* const engine_ = nullptr;
std::vector<AudioCodec> recv_codecs_;
std::vector<AudioCodec> send_codecs_;
rtc::scoped_ptr<webrtc::CodecInst> send_codec_;
- bool send_bitrate_setting_;
- int send_bitrate_bps_;
+ bool send_bitrate_setting_ = false;
+ int send_bitrate_bps_ = 0;
AudioOptions options_;
- bool dtmf_allowed_;
- bool desired_playout_;
- bool nack_enabled_;
- bool playout_;
- bool typing_noise_detected_;
- SendFlags desired_send_;
- SendFlags send_;
- webrtc::Call* const call_;
+ rtc::Optional<int> dtmf_payload_type_;
+ bool desired_playout_ = false;
+ bool nack_enabled_ = false;
+ bool playout_ = false;
+ SendFlags desired_send_ = SEND_NOTHING;
+ SendFlags send_ = SEND_NOTHING;
+ webrtc::Call* const call_ = nullptr;
// SSRC of unsignalled receive stream, or -1 if there isn't one.
int64_t default_recv_ssrc_ = -1;
// Volume for unsignalled stream, which may be set before the stream exists.
double default_recv_volume_ = 1.0;
- // SSRC to use for RTCP receiver reports; default to 1 in case of no signaled
+ // Default SSRC to use for RTCP receiver reports in case of no signaled
// send streams. See: https://code.google.com/p/webrtc/issues/detail?id=4740
- uint32_t receiver_reports_ssrc_ = 1;
+ // and https://code.google.com/p/chromium/issues/detail?id=547661
+ uint32_t receiver_reports_ssrc_ = 0xFA17FA17u;
class WebRtcAudioSendStream;
std::map<uint32_t, WebRtcAudioSendStream*> send_streams_;
- std::vector<RtpHeaderExtension> send_extensions_;
+ std::vector<webrtc::RtpExtension> send_rtp_extensions_;
class WebRtcAudioReceiveStream;
- std::map<uint32_t, WebRtcAudioReceiveStream*> receive_channels_;
- std::map<uint32_t, webrtc::AudioReceiveStream*> receive_streams_;
- std::map<uint32_t, StreamParams> receive_stream_params_;
- // receive_channels_ can be read from WebRtc callback thread. Access from
- // the WebRtc thread must be synchronized with edits on the worker thread.
- // Reads on the worker thread are ok.
- std::vector<RtpHeaderExtension> receive_extensions_;
+ std::map<uint32_t, WebRtcAudioReceiveStream*> recv_streams_;
std::vector<webrtc::RtpExtension> recv_rtp_extensions_;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcVoiceMediaChannel);
};
-
} // namespace cricket
#endif // TALK_MEDIA_WEBRTCVOICEENGINE_H_
diff --git a/talk/media/webrtc/webrtcvoiceengine_unittest.cc b/talk/media/webrtc/webrtcvoiceengine_unittest.cc
index ce5115cb10..a62bcb225f 100644
--- a/talk/media/webrtc/webrtcvoiceengine_unittest.cc
+++ b/talk/media/webrtc/webrtcvoiceengine_unittest.cc
@@ -25,6 +25,7 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "webrtc/base/arraysize.h"
#include "webrtc/base/byteorder.h"
#include "webrtc/base/gunit.h"
#include "webrtc/call.h"
@@ -53,10 +54,6 @@ const cricket::AudioCodec kCn8000Codec(13, "CN", 8000, 0, 1, 0);
const cricket::AudioCodec kCn16000Codec(105, "CN", 16000, 0, 1, 0);
const cricket::AudioCodec kTelephoneEventCodec(106, "telephone-event", 8000, 0,
1, 0);
-const cricket::AudioCodec* const kAudioCodecs[] = {
- &kPcmuCodec, &kIsacCodec, &kOpusCodec, &kG722CodecVoE, &kRedCodec,
- &kCn8000Codec, &kCn16000Codec, &kTelephoneEventCodec,
-};
const uint32_t kSsrc1 = 0x99;
const uint32_t kSsrc2 = 0x98;
const uint32_t kSsrcs4[] = { 1, 2, 3, 4 };
@@ -67,37 +64,22 @@ class FakeVoEWrapper : public cricket::VoEWrapper {
: cricket::VoEWrapper(engine, // processing
engine, // base
engine, // codec
- engine, // dtmf
engine, // hw
engine, // network
engine, // rtp
engine) { // volume
}
};
-
-class FakeVoETraceWrapper : public cricket::VoETraceWrapper {
- public:
- int SetTraceFilter(const unsigned int filter) override {
- filter_ = filter;
- return 0;
- }
- int SetTraceFile(const char* fileNameUTF8) override { return 0; }
- int SetTraceCallback(webrtc::TraceCallback* callback) override { return 0; }
- unsigned int filter_;
-};
} // namespace
class WebRtcVoiceEngineTestFake : public testing::Test {
public:
WebRtcVoiceEngineTestFake()
: call_(webrtc::Call::Config()),
- voe_(kAudioCodecs, ARRAY_SIZE(kAudioCodecs)),
- trace_wrapper_(new FakeVoETraceWrapper()),
- engine_(new FakeVoEWrapper(&voe_), trace_wrapper_),
+ engine_(new FakeVoEWrapper(&voe_)),
channel_(nullptr) {
send_parameters_.codecs.push_back(kPcmuCodec);
recv_parameters_.codecs.push_back(kPcmuCodec);
- options_adjust_agc_.adjust_agc_delta.Set(-10);
}
bool SetupEngine() {
if (!engine_.Init(rtc::Thread::Current())) {
@@ -123,12 +105,10 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
void SetupForMultiSendStream() {
EXPECT_TRUE(SetupEngineWithSendStream());
// Remove stream added in Setup.
- int default_channel_num = voe_.GetLastChannel();
- EXPECT_EQ(kSsrc1, voe_.GetLocalSSRC(default_channel_num));
+ EXPECT_TRUE(call_.GetAudioSendStream(kSsrc1));
EXPECT_TRUE(channel_->RemoveSendStream(kSsrc1));
-
// Verify the channel does not exist.
- EXPECT_EQ(-1, voe_.GetChannelFromLocalSsrc(kSsrc1));
+ EXPECT_FALSE(call_.GetAudioSendStream(kSsrc1));
}
void DeliverPacket(const void* data, int len) {
rtc::Buffer packet(reinterpret_cast<const uint8_t*>(data), len);
@@ -139,6 +119,24 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
engine_.Terminate();
}
+ const cricket::FakeAudioSendStream& GetSendStream(uint32_t ssrc) {
+ const auto* send_stream = call_.GetAudioSendStream(ssrc);
+ EXPECT_TRUE(send_stream);
+ return *send_stream;
+ }
+
+ const webrtc::AudioSendStream::Config& GetSendStreamConfig(uint32_t ssrc) {
+ const auto* send_stream = call_.GetAudioSendStream(ssrc);
+ EXPECT_TRUE(send_stream);
+ return send_stream->GetConfig();
+ }
+
+ const webrtc::AudioReceiveStream::Config& GetRecvStreamConfig(uint32_t ssrc) {
+ const auto* recv_stream = call_.GetAudioReceiveStream(ssrc);
+ EXPECT_TRUE(recv_stream);
+ return recv_stream->GetConfig();
+ }
+
void TestInsertDtmf(uint32_t ssrc, bool caller) {
EXPECT_TRUE(engine_.Init(rtc::Thread::Current()));
channel_ = engine_.CreateChannel(&call_, cricket::AudioOptions());
@@ -154,39 +152,30 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
EXPECT_FALSE(channel_->CanInsertDtmf());
- EXPECT_FALSE(channel_->InsertDtmf(ssrc, 1, 111, cricket::DF_SEND));
+ EXPECT_FALSE(channel_->InsertDtmf(ssrc, 1, 111));
send_parameters_.codecs.push_back(kTelephoneEventCodec);
EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
EXPECT_TRUE(channel_->CanInsertDtmf());
if (!caller) {
// If this is callee, there's no active send channel yet.
- EXPECT_FALSE(channel_->InsertDtmf(ssrc, 2, 123, cricket::DF_SEND));
+ EXPECT_FALSE(channel_->InsertDtmf(ssrc, 2, 123));
EXPECT_TRUE(channel_->AddSendStream(
cricket::StreamParams::CreateLegacy(kSsrc1)));
}
// Check we fail if the ssrc is invalid.
- EXPECT_FALSE(channel_->InsertDtmf(-1, 1, 111, cricket::DF_SEND));
-
- // Test send
- int channel_id = voe_.GetLastChannel();
- EXPECT_FALSE(voe_.WasSendTelephoneEventCalled(channel_id, 2, 123));
- EXPECT_TRUE(channel_->InsertDtmf(ssrc, 2, 123, cricket::DF_SEND));
- EXPECT_TRUE(voe_.WasSendTelephoneEventCalled(channel_id, 2, 123));
-
- // Test play
- EXPECT_FALSE(voe_.WasPlayDtmfToneCalled(3, 134));
- EXPECT_TRUE(channel_->InsertDtmf(ssrc, 3, 134, cricket::DF_PLAY));
- EXPECT_TRUE(voe_.WasPlayDtmfToneCalled(3, 134));
-
- // Test send and play
- EXPECT_FALSE(voe_.WasSendTelephoneEventCalled(channel_id, 4, 145));
- EXPECT_FALSE(voe_.WasPlayDtmfToneCalled(4, 145));
- EXPECT_TRUE(channel_->InsertDtmf(ssrc, 4, 145,
- cricket::DF_PLAY | cricket::DF_SEND));
- EXPECT_TRUE(voe_.WasSendTelephoneEventCalled(channel_id, 4, 145));
- EXPECT_TRUE(voe_.WasPlayDtmfToneCalled(4, 145));
+ EXPECT_FALSE(channel_->InsertDtmf(-1, 1, 111));
+
+ // Test send.
+ cricket::FakeAudioSendStream::TelephoneEvent telephone_event =
+ GetSendStream(kSsrc1).GetLatestTelephoneEvent();
+ EXPECT_EQ(-1, telephone_event.payload_type);
+ EXPECT_TRUE(channel_->InsertDtmf(ssrc, 2, 123));
+ telephone_event = GetSendStream(kSsrc1).GetLatestTelephoneEvent();
+ EXPECT_EQ(kTelephoneEventCodec.id, telephone_event.payload_type);
+ EXPECT_EQ(2, telephone_event.event_code);
+ EXPECT_EQ(123, telephone_event.duration_ms);
}
// Test that send bandwidth is set correctly.
@@ -211,81 +200,85 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
void TestSetSendRtpHeaderExtensions(const std::string& ext) {
EXPECT_TRUE(SetupEngineWithSendStream());
- int channel_num = voe_.GetLastChannel();
// Ensure extensions are off by default.
- EXPECT_EQ(-1, voe_.GetSendRtpExtensionId(channel_num, ext));
+ EXPECT_EQ(0u, GetSendStreamConfig(kSsrc1).rtp.extensions.size());
// Ensure unknown extensions won't cause an error.
send_parameters_.extensions.push_back(cricket::RtpHeaderExtension(
"urn:ietf:params:unknownextention", 1));
EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
- EXPECT_EQ(-1, voe_.GetSendRtpExtensionId(channel_num, ext));
+ EXPECT_EQ(0u, GetSendStreamConfig(kSsrc1).rtp.extensions.size());
// Ensure extensions stay off with an empty list of headers.
send_parameters_.extensions.clear();
EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
- EXPECT_EQ(-1, voe_.GetSendRtpExtensionId(channel_num, ext));
+ EXPECT_EQ(0u, GetSendStreamConfig(kSsrc1).rtp.extensions.size());
// Ensure extension is set properly.
const int id = 1;
send_parameters_.extensions.push_back(cricket::RtpHeaderExtension(ext, id));
EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
- EXPECT_EQ(id, voe_.GetSendRtpExtensionId(channel_num, ext));
+ EXPECT_EQ(1u, GetSendStreamConfig(kSsrc1).rtp.extensions.size());
+ EXPECT_EQ(ext, GetSendStreamConfig(kSsrc1).rtp.extensions[0].name);
+ EXPECT_EQ(id, GetSendStreamConfig(kSsrc1).rtp.extensions[0].id);
- // Ensure extension is set properly on new channels.
+ // Ensure extension is set properly on new stream.
EXPECT_TRUE(channel_->AddSendStream(
cricket::StreamParams::CreateLegacy(kSsrc2)));
- int new_channel_num = voe_.GetLastChannel();
- EXPECT_NE(channel_num, new_channel_num);
- EXPECT_EQ(id, voe_.GetSendRtpExtensionId(new_channel_num, ext));
+ EXPECT_NE(call_.GetAudioSendStream(kSsrc1),
+ call_.GetAudioSendStream(kSsrc2));
+ EXPECT_EQ(1u, GetSendStreamConfig(kSsrc2).rtp.extensions.size());
+ EXPECT_EQ(ext, GetSendStreamConfig(kSsrc2).rtp.extensions[0].name);
+ EXPECT_EQ(id, GetSendStreamConfig(kSsrc2).rtp.extensions[0].id);
// Ensure all extensions go back off with an empty list.
send_parameters_.codecs.push_back(kPcmuCodec);
send_parameters_.extensions.clear();
EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
- EXPECT_EQ(-1, voe_.GetSendRtpExtensionId(channel_num, ext));
- EXPECT_EQ(-1, voe_.GetSendRtpExtensionId(new_channel_num, ext));
+ EXPECT_EQ(0u, GetSendStreamConfig(kSsrc1).rtp.extensions.size());
+ EXPECT_EQ(0u, GetSendStreamConfig(kSsrc2).rtp.extensions.size());
}
void TestSetRecvRtpHeaderExtensions(const std::string& ext) {
EXPECT_TRUE(SetupEngineWithRecvStream());
- int channel_num = voe_.GetLastChannel();
// Ensure extensions are off by default.
- EXPECT_EQ(-1, voe_.GetReceiveRtpExtensionId(channel_num, ext));
+ EXPECT_EQ(0u, GetRecvStreamConfig(kSsrc1).rtp.extensions.size());
- cricket::AudioRecvParameters parameters;
// Ensure unknown extensions won't cause an error.
- parameters.extensions.push_back(cricket::RtpHeaderExtension(
+ recv_parameters_.extensions.push_back(cricket::RtpHeaderExtension(
"urn:ietf:params:unknownextention", 1));
- EXPECT_TRUE(channel_->SetRecvParameters(parameters));
- EXPECT_EQ(-1, voe_.GetReceiveRtpExtensionId(channel_num, ext));
+ EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
+ EXPECT_EQ(0u, GetRecvStreamConfig(kSsrc1).rtp.extensions.size());
// Ensure extensions stay off with an empty list of headers.
- parameters.extensions.clear();
- EXPECT_TRUE(channel_->SetRecvParameters(parameters));
- EXPECT_EQ(-1, voe_.GetReceiveRtpExtensionId(channel_num, ext));
+ recv_parameters_.extensions.clear();
+ EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
+ EXPECT_EQ(0u, GetRecvStreamConfig(kSsrc1).rtp.extensions.size());
// Ensure extension is set properly.
const int id = 2;
- parameters.extensions.push_back(cricket::RtpHeaderExtension(ext, id));
- EXPECT_TRUE(channel_->SetRecvParameters(parameters));
- EXPECT_EQ(id, voe_.GetReceiveRtpExtensionId(channel_num, ext));
+ recv_parameters_.extensions.push_back(cricket::RtpHeaderExtension(ext, id));
+ EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
+ EXPECT_EQ(1u, GetRecvStreamConfig(kSsrc1).rtp.extensions.size());
+ EXPECT_EQ(ext, GetRecvStreamConfig(kSsrc1).rtp.extensions[0].name);
+ EXPECT_EQ(id, GetRecvStreamConfig(kSsrc1).rtp.extensions[0].id);
- // Ensure extension is set properly on new channel.
- // The first stream to occupy the default channel.
+ // Ensure extension is set properly on new stream.
EXPECT_TRUE(channel_->AddRecvStream(
cricket::StreamParams::CreateLegacy(kSsrc2)));
- int new_channel_num = voe_.GetLastChannel();
- EXPECT_NE(channel_num, new_channel_num);
- EXPECT_EQ(id, voe_.GetReceiveRtpExtensionId(new_channel_num, ext));
+ EXPECT_NE(call_.GetAudioReceiveStream(kSsrc1),
+ call_.GetAudioReceiveStream(kSsrc2));
+ EXPECT_EQ(1u, GetRecvStreamConfig(kSsrc2).rtp.extensions.size());
+ EXPECT_EQ(ext, GetRecvStreamConfig(kSsrc2).rtp.extensions[0].name);
+ EXPECT_EQ(id, GetRecvStreamConfig(kSsrc2).rtp.extensions[0].id);
// Ensure all extensions go back off with an empty list.
- parameters.extensions.clear();
- EXPECT_TRUE(channel_->SetRecvParameters(parameters));
- EXPECT_EQ(-1, voe_.GetReceiveRtpExtensionId(channel_num, ext));
- EXPECT_EQ(-1, voe_.GetReceiveRtpExtensionId(new_channel_num, ext));
+ recv_parameters_.extensions.clear();
+ EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
+ EXPECT_EQ(0u, GetRecvStreamConfig(kSsrc1).rtp.extensions.size());
+ EXPECT_EQ(0u, GetRecvStreamConfig(kSsrc2).rtp.extensions.size());
}
webrtc::AudioSendStream::Stats GetAudioSendStreamStats() const {
@@ -313,7 +306,8 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
s->SetStats(GetAudioSendStreamStats());
}
}
- void VerifyVoiceSenderInfo(const cricket::VoiceSenderInfo& info) {
+ void VerifyVoiceSenderInfo(const cricket::VoiceSenderInfo& info,
+ bool is_sending) {
const auto stats = GetAudioSendStreamStats();
EXPECT_EQ(info.ssrc(), stats.local_ssrc);
EXPECT_EQ(info.bytes_sent, stats.bytes_sent);
@@ -331,8 +325,8 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
EXPECT_EQ(info.echo_return_loss, stats.echo_return_loss);
EXPECT_EQ(info.echo_return_loss_enhancement,
stats.echo_return_loss_enhancement);
- // TODO(solenberg): Move typing noise detection into AudioSendStream.
- // EXPECT_EQ(info.typing_noise_detected, stats.typing_noise_detected);
+ EXPECT_EQ(info.typing_noise_detected,
+ stats.typing_noise_detected && is_sending);
}
webrtc::AudioReceiveStream::Stats GetAudioReceiveStreamStats() const {
@@ -401,13 +395,10 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
protected:
cricket::FakeCall call_;
cricket::FakeWebRtcVoiceEngine voe_;
- FakeVoETraceWrapper* trace_wrapper_;
cricket::WebRtcVoiceEngine engine_;
cricket::VoiceMediaChannel* channel_;
-
cricket::AudioSendParameters send_parameters_;
cricket::AudioRecvParameters recv_parameters_;
- cricket::AudioOptions options_adjust_agc_;
};
// Tests that our stub library "works".
@@ -448,32 +439,33 @@ TEST_F(WebRtcVoiceEngineTestFake, FindCodec) {
cricket::AudioCodec codec;
webrtc::CodecInst codec_inst;
// Find PCMU with explicit clockrate and bitrate.
- EXPECT_TRUE(engine_.FindWebRtcCodec(kPcmuCodec, &codec_inst));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(kPcmuCodec, &codec_inst));
// Find ISAC with explicit clockrate and 0 bitrate.
- EXPECT_TRUE(engine_.FindWebRtcCodec(kIsacCodec, &codec_inst));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(kIsacCodec, &codec_inst));
// Find telephone-event with explicit clockrate and 0 bitrate.
- EXPECT_TRUE(engine_.FindWebRtcCodec(kTelephoneEventCodec, &codec_inst));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(kTelephoneEventCodec,
+ &codec_inst));
// Find ISAC with a different payload id.
codec = kIsacCodec;
codec.id = 127;
- EXPECT_TRUE(engine_.FindWebRtcCodec(codec, &codec_inst));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(codec, &codec_inst));
EXPECT_EQ(codec.id, codec_inst.pltype);
// Find PCMU with a 0 clockrate.
codec = kPcmuCodec;
codec.clockrate = 0;
- EXPECT_TRUE(engine_.FindWebRtcCodec(codec, &codec_inst));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(codec, &codec_inst));
EXPECT_EQ(codec.id, codec_inst.pltype);
EXPECT_EQ(8000, codec_inst.plfreq);
// Find PCMU with a 0 bitrate.
codec = kPcmuCodec;
codec.bitrate = 0;
- EXPECT_TRUE(engine_.FindWebRtcCodec(codec, &codec_inst));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(codec, &codec_inst));
EXPECT_EQ(codec.id, codec_inst.pltype);
EXPECT_EQ(64000, codec_inst.rate);
// Find ISAC with an explicit bitrate.
codec = kIsacCodec;
codec.bitrate = 32000;
- EXPECT_TRUE(engine_.FindWebRtcCodec(codec, &codec_inst));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(codec, &codec_inst));
EXPECT_EQ(codec.id, codec_inst.pltype);
EXPECT_EQ(32000, codec_inst.rate);
}
@@ -492,14 +484,13 @@ TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecs) {
cricket::StreamParams::CreateLegacy(kSsrc1)));
int channel_num = voe_.GetLastChannel();
webrtc::CodecInst gcodec;
- rtc::strcpyn(gcodec.plname, ARRAY_SIZE(gcodec.plname), "ISAC");
+ rtc::strcpyn(gcodec.plname, arraysize(gcodec.plname), "ISAC");
gcodec.plfreq = 16000;
gcodec.channels = 1;
EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num, gcodec));
EXPECT_EQ(106, gcodec.pltype);
EXPECT_STREQ("ISAC", gcodec.plname);
- rtc::strcpyn(gcodec.plname, ARRAY_SIZE(gcodec.plname),
- "telephone-event");
+ rtc::strcpyn(gcodec.plname, arraysize(gcodec.plname), "telephone-event");
gcodec.plfreq = 8000;
EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num, gcodec));
EXPECT_EQ(126, gcodec.pltype);
@@ -537,7 +528,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecsWithOpusNoStereo) {
cricket::StreamParams::CreateLegacy(kSsrc1)));
int channel_num = voe_.GetLastChannel();
webrtc::CodecInst opus;
- engine_.FindWebRtcCodec(kOpusCodec, &opus);
+ cricket::WebRtcVoiceEngine::ToCodecInst(kOpusCodec, &opus);
// Even without stereo parameters, recv codecs still specify channels = 2.
EXPECT_EQ(2, opus.channels);
EXPECT_EQ(111, opus.pltype);
@@ -560,7 +551,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecsWithOpus0Stereo) {
cricket::StreamParams::CreateLegacy(kSsrc1)));
int channel_num2 = voe_.GetLastChannel();
webrtc::CodecInst opus;
- engine_.FindWebRtcCodec(kOpusCodec, &opus);
+ cricket::WebRtcVoiceEngine::ToCodecInst(kOpusCodec, &opus);
// Even when stereo is off, recv codecs still specify channels = 2.
EXPECT_EQ(2, opus.channels);
EXPECT_EQ(111, opus.pltype);
@@ -583,7 +574,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecsWithOpus1Stereo) {
cricket::StreamParams::CreateLegacy(kSsrc1)));
int channel_num2 = voe_.GetLastChannel();
webrtc::CodecInst opus;
- engine_.FindWebRtcCodec(kOpusCodec, &opus);
+ cricket::WebRtcVoiceEngine::ToCodecInst(kOpusCodec, &opus);
EXPECT_EQ(2, opus.channels);
EXPECT_EQ(111, opus.pltype);
EXPECT_STREQ("opus", opus.plname);
@@ -606,14 +597,13 @@ TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecsWithMultipleStreams) {
cricket::StreamParams::CreateLegacy(kSsrc1)));
int channel_num2 = voe_.GetLastChannel();
webrtc::CodecInst gcodec;
- rtc::strcpyn(gcodec.plname, ARRAY_SIZE(gcodec.plname), "ISAC");
+ rtc::strcpyn(gcodec.plname, arraysize(gcodec.plname), "ISAC");
gcodec.plfreq = 16000;
gcodec.channels = 1;
EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num2, gcodec));
EXPECT_EQ(106, gcodec.pltype);
EXPECT_STREQ("ISAC", gcodec.plname);
- rtc::strcpyn(gcodec.plname, ARRAY_SIZE(gcodec.plname),
- "telephone-event");
+ rtc::strcpyn(gcodec.plname, arraysize(gcodec.plname), "telephone-event");
gcodec.plfreq = 8000;
gcodec.channels = 1;
EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num2, gcodec));
@@ -630,7 +620,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecsAfterAddingStreams) {
int channel_num2 = voe_.GetLastChannel();
webrtc::CodecInst gcodec;
- rtc::strcpyn(gcodec.plname, ARRAY_SIZE(gcodec.plname), "ISAC");
+ rtc::strcpyn(gcodec.plname, arraysize(gcodec.plname), "ISAC");
gcodec.plfreq = 16000;
gcodec.channels = 1;
EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num2, gcodec));
@@ -669,7 +659,7 @@ TEST_F(WebRtcVoiceEngineTestFake, AddRecvCodecsWhilePlaying) {
int channel_num = voe_.GetLastChannel();
EXPECT_TRUE(voe_.GetPlayout(channel_num));
webrtc::CodecInst gcodec;
- EXPECT_TRUE(engine_.FindWebRtcCodec(kOpusCodec, &gcodec));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(kOpusCodec, &gcodec));
EXPECT_EQ(kOpusCodec.id, gcodec.pltype);
}
@@ -782,7 +772,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecs) {
EXPECT_FALSE(voe_.GetRED(channel_num));
EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false));
EXPECT_EQ(105, voe_.GetSendCNPayloadType(channel_num, true));
- EXPECT_EQ(106, voe_.GetSendTelephoneEventPayloadType(channel_num));
+ EXPECT_FALSE(channel_->CanInsertDtmf());
}
// Test that VoE Channel doesn't call SetSendCodec again if same codec is tried
@@ -1623,7 +1613,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsDTMFOnTop) {
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
EXPECT_EQ(96, gcodec.pltype);
EXPECT_STREQ("ISAC", gcodec.plname);
- EXPECT_EQ(98, voe_.GetSendTelephoneEventPayloadType(channel_num));
+ EXPECT_TRUE(channel_->CanInsertDtmf());
}
// Test that we can set send codecs even with CN codec as the first
@@ -1669,7 +1659,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCNandDTMFAsCaller) {
EXPECT_FALSE(voe_.GetRED(channel_num));
EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false));
EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true));
- EXPECT_EQ(98, voe_.GetSendTelephoneEventPayloadType(channel_num));
+ EXPECT_TRUE(channel_->CanInsertDtmf());
}
// Test that we set VAD and DTMF types correctly as callee.
@@ -1702,7 +1692,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCNandDTMFAsCallee) {
EXPECT_FALSE(voe_.GetRED(channel_num));
EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false));
EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true));
- EXPECT_EQ(98, voe_.GetSendTelephoneEventPayloadType(channel_num));
+ EXPECT_TRUE(channel_->CanInsertDtmf());
}
// Test that we only apply VAD if we have a CN codec that matches the
@@ -1766,7 +1756,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCaseInsensitive) {
EXPECT_FALSE(voe_.GetRED(channel_num));
EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false));
EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true));
- EXPECT_EQ(98, voe_.GetSendTelephoneEventPayloadType(channel_num));
+ EXPECT_TRUE(channel_->CanInsertDtmf());
}
// Test that we set up RED correctly as caller.
@@ -1976,21 +1966,16 @@ TEST_F(WebRtcVoiceEngineTestFake, CreateAndDeleteMultipleSendStreams) {
for (uint32_t ssrc : kSsrcs4) {
EXPECT_TRUE(channel_->AddSendStream(
cricket::StreamParams::CreateLegacy(ssrc)));
- EXPECT_NE(nullptr, call_.GetAudioSendStream(ssrc));
-
// Verify that we are in a sending state for all the created streams.
- int channel_num = voe_.GetChannelFromLocalSsrc(ssrc);
- EXPECT_TRUE(voe_.GetSend(channel_num));
+ EXPECT_TRUE(voe_.GetSend(GetSendStreamConfig(ssrc).voe_channel_id));
}
- EXPECT_EQ(ARRAY_SIZE(kSsrcs4), call_.GetAudioSendStreams().size());
+ EXPECT_EQ(arraysize(kSsrcs4), call_.GetAudioSendStreams().size());
// Delete the send streams.
for (uint32_t ssrc : kSsrcs4) {
EXPECT_TRUE(channel_->RemoveSendStream(ssrc));
- EXPECT_EQ(nullptr, call_.GetAudioSendStream(ssrc));
- // Stream should already be deleted.
+ EXPECT_FALSE(call_.GetAudioSendStream(ssrc));
EXPECT_FALSE(channel_->RemoveSendStream(ssrc));
- EXPECT_EQ(-1, voe_.GetChannelFromLocalSsrc(ssrc));
}
EXPECT_EQ(0u, call_.GetAudioSendStreams().size());
}
@@ -2015,7 +2000,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsWithMultipleSendStreams) {
// Verify ISAC and VAD are corrected configured on all send channels.
webrtc::CodecInst gcodec;
for (uint32_t ssrc : kSsrcs4) {
- int channel_num = voe_.GetChannelFromLocalSsrc(ssrc);
+ int channel_num = GetSendStreamConfig(ssrc).voe_channel_id;
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
EXPECT_STREQ("ISAC", gcodec.plname);
EXPECT_TRUE(voe_.GetVAD(channel_num));
@@ -2026,7 +2011,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsWithMultipleSendStreams) {
parameters.codecs[0] = kPcmuCodec;
EXPECT_TRUE(channel_->SetSendParameters(parameters));
for (uint32_t ssrc : kSsrcs4) {
- int channel_num = voe_.GetChannelFromLocalSsrc(ssrc);
+ int channel_num = GetSendStreamConfig(ssrc).voe_channel_id;
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
EXPECT_STREQ("PCMU", gcodec.plname);
EXPECT_FALSE(voe_.GetVAD(channel_num));
@@ -2049,7 +2034,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendWithMultipleSendStreams) {
EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
for (uint32_t ssrc : kSsrcs4) {
// Verify that we are in a sending state for all the send streams.
- int channel_num = voe_.GetChannelFromLocalSsrc(ssrc);
+ int channel_num = GetSendStreamConfig(ssrc).voe_channel_id;
EXPECT_TRUE(voe_.GetSend(channel_num));
}
@@ -2057,7 +2042,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendWithMultipleSendStreams) {
EXPECT_TRUE(channel_->SetSend(cricket::SEND_NOTHING));
for (uint32_t ssrc : kSsrcs4) {
// Verify that we are in a stop state for all the send streams.
- int channel_num = voe_.GetChannelFromLocalSsrc(ssrc);
+ int channel_num = GetSendStreamConfig(ssrc).voe_channel_id;
EXPECT_FALSE(voe_.GetSend(channel_num));
}
}
@@ -2087,9 +2072,9 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStatsWithMultipleSendStreams) {
EXPECT_EQ(true, channel_->GetStats(&info));
// We have added 4 send streams. We should see empty stats for all.
- EXPECT_EQ(static_cast<size_t>(ARRAY_SIZE(kSsrcs4)), info.senders.size());
+ EXPECT_EQ(static_cast<size_t>(arraysize(kSsrcs4)), info.senders.size());
for (const auto& sender : info.senders) {
- VerifyVoiceSenderInfo(sender);
+ VerifyVoiceSenderInfo(sender, false);
}
// We have added one receive stream. We should see empty stats.
@@ -2102,7 +2087,7 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStatsWithMultipleSendStreams) {
cricket::VoiceMediaInfo info;
EXPECT_TRUE(channel_->RemoveRecvStream(kSsrc2));
EXPECT_EQ(true, channel_->GetStats(&info));
- EXPECT_EQ(static_cast<size_t>(ARRAY_SIZE(kSsrcs4)), info.senders.size());
+ EXPECT_EQ(static_cast<size_t>(arraysize(kSsrcs4)), info.senders.size());
EXPECT_EQ(0u, info.receivers.size());
}
@@ -2113,7 +2098,7 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStatsWithMultipleSendStreams) {
DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame));
SetAudioReceiveStreamStats();
EXPECT_EQ(true, channel_->GetStats(&info));
- EXPECT_EQ(static_cast<size_t>(ARRAY_SIZE(kSsrcs4)), info.senders.size());
+ EXPECT_EQ(static_cast<size_t>(arraysize(kSsrcs4)), info.senders.size());
EXPECT_EQ(1u, info.receivers.size());
VerifyVoiceReceiverInfo(info.receivers[0]);
}
@@ -2173,96 +2158,17 @@ TEST_F(WebRtcVoiceEngineTestFake, PlayoutWithMultipleStreams) {
EXPECT_FALSE(voe_.GetPlayout(channel_num1));
}
-// Test that we can set the devices to use.
-TEST_F(WebRtcVoiceEngineTestFake, SetDevices) {
- EXPECT_TRUE(SetupEngineWithSendStream());
- int send_channel = voe_.GetLastChannel();
- EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
- int recv_channel = voe_.GetLastChannel();
- EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
-
- cricket::Device default_dev(cricket::kFakeDefaultDeviceName,
- cricket::kFakeDefaultDeviceId);
- cricket::Device dev(cricket::kFakeDeviceName,
- cricket::kFakeDeviceId);
-
- // Test SetDevices() while not sending or playing.
- EXPECT_TRUE(engine_.SetDevices(&default_dev, &default_dev));
-
- // Test SetDevices() while sending and playing.
- EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
- EXPECT_TRUE(channel_->SetPlayout(true));
- EXPECT_TRUE(voe_.GetSend(send_channel));
- EXPECT_TRUE(voe_.GetPlayout(recv_channel));
-
- EXPECT_TRUE(engine_.SetDevices(&dev, &dev));
-
- EXPECT_TRUE(voe_.GetSend(send_channel));
- EXPECT_TRUE(voe_.GetPlayout(recv_channel));
-
- // Test that failure to open newly selected devices does not prevent opening
- // ones after that.
- voe_.set_playout_fail_channel(recv_channel);
- voe_.set_send_fail_channel(send_channel);
-
- EXPECT_FALSE(engine_.SetDevices(&default_dev, &default_dev));
-
- EXPECT_FALSE(voe_.GetSend(send_channel));
- EXPECT_FALSE(voe_.GetPlayout(recv_channel));
-
- voe_.set_playout_fail_channel(-1);
- voe_.set_send_fail_channel(-1);
-
- EXPECT_TRUE(engine_.SetDevices(&dev, &dev));
-
- EXPECT_TRUE(voe_.GetSend(send_channel));
- EXPECT_TRUE(voe_.GetPlayout(recv_channel));
-}
-
-// Test that we can set the devices to use even if we failed to
-// open the initial ones.
-TEST_F(WebRtcVoiceEngineTestFake, SetDevicesWithInitiallyBadDevices) {
- EXPECT_TRUE(SetupEngineWithSendStream());
- int send_channel = voe_.GetLastChannel();
- EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
- int recv_channel = voe_.GetLastChannel();
- EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
-
- cricket::Device default_dev(cricket::kFakeDefaultDeviceName,
- cricket::kFakeDefaultDeviceId);
- cricket::Device dev(cricket::kFakeDeviceName,
- cricket::kFakeDeviceId);
-
- // Test that failure to open devices selected before starting
- // send/play does not prevent opening newly selected ones after that.
- voe_.set_playout_fail_channel(recv_channel);
- voe_.set_send_fail_channel(send_channel);
-
- EXPECT_TRUE(engine_.SetDevices(&default_dev, &default_dev));
-
- EXPECT_FALSE(channel_->SetSend(cricket::SEND_MICROPHONE));
- EXPECT_FALSE(channel_->SetPlayout(true));
- EXPECT_FALSE(voe_.GetSend(send_channel));
- EXPECT_FALSE(voe_.GetPlayout(recv_channel));
-
- voe_.set_playout_fail_channel(-1);
- voe_.set_send_fail_channel(-1);
-
- EXPECT_TRUE(engine_.SetDevices(&dev, &dev));
-
- EXPECT_TRUE(voe_.GetSend(send_channel));
- EXPECT_TRUE(voe_.GetPlayout(recv_channel));
-}
-
// Test that we can create a channel configured for Codian bridges,
// and start sending on it.
TEST_F(WebRtcVoiceEngineTestFake, CodianSend) {
EXPECT_TRUE(SetupEngineWithSendStream());
+ cricket::AudioOptions options_adjust_agc;
+ options_adjust_agc.adjust_agc_delta = rtc::Optional<int>(-10);
int channel_num = voe_.GetLastChannel();
webrtc::AgcConfig agc_config;
EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
EXPECT_EQ(0, agc_config.targetLeveldBOv);
- send_parameters_.options = options_adjust_agc_;
+ send_parameters_.options = options_adjust_agc;
EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
EXPECT_TRUE(voe_.GetSend(channel_num));
@@ -2271,7 +2177,6 @@ TEST_F(WebRtcVoiceEngineTestFake, CodianSend) {
EXPECT_TRUE(channel_->SetSend(cricket::SEND_NOTHING));
EXPECT_FALSE(voe_.GetSend(channel_num));
EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
- EXPECT_EQ(0, agc_config.targetLeveldBOv); // level was restored
}
TEST_F(WebRtcVoiceEngineTestFake, TxAgcConfigViaOptions) {
@@ -2279,14 +2184,12 @@ TEST_F(WebRtcVoiceEngineTestFake, TxAgcConfigViaOptions) {
webrtc::AgcConfig agc_config;
EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
EXPECT_EQ(0, agc_config.targetLeveldBOv);
-
- cricket::AudioOptions options;
- options.tx_agc_target_dbov.Set(3);
- options.tx_agc_digital_compression_gain.Set(9);
- options.tx_agc_limiter.Set(true);
- options.auto_gain_control.Set(true);
- EXPECT_TRUE(engine_.SetOptions(options));
-
+ send_parameters_.options.tx_agc_target_dbov = rtc::Optional<uint16_t>(3);
+ send_parameters_.options.tx_agc_digital_compression_gain =
+ rtc::Optional<uint16_t>(9);
+ send_parameters_.options.tx_agc_limiter = rtc::Optional<bool>(true);
+ send_parameters_.options.auto_gain_control = rtc::Optional<bool>(true);
+ EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
EXPECT_EQ(3, agc_config.targetLeveldBOv);
EXPECT_EQ(9, agc_config.digitalCompressionGaindB);
@@ -2294,19 +2197,18 @@ TEST_F(WebRtcVoiceEngineTestFake, TxAgcConfigViaOptions) {
// Check interaction with adjust_agc_delta. Both should be respected, for
// backwards compatibility.
- options.adjust_agc_delta.Set(-10);
- EXPECT_TRUE(engine_.SetOptions(options));
-
+ send_parameters_.options.adjust_agc_delta = rtc::Optional<int>(-10);
+ EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
EXPECT_EQ(13, agc_config.targetLeveldBOv);
}
TEST_F(WebRtcVoiceEngineTestFake, SampleRatesViaOptions) {
EXPECT_TRUE(SetupEngineWithSendStream());
- cricket::AudioOptions options;
- options.recording_sample_rate.Set(48000u);
- options.playout_sample_rate.Set(44100u);
- EXPECT_TRUE(engine_.SetOptions(options));
+ send_parameters_.options.recording_sample_rate =
+ rtc::Optional<uint32_t>(48000);
+ send_parameters_.options.playout_sample_rate = rtc::Optional<uint32_t>(44100);
+ EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
unsigned int recording_sample_rate, playout_sample_rate;
EXPECT_EQ(0, voe_.RecordingSampleRate(&recording_sample_rate));
@@ -2315,30 +2217,11 @@ TEST_F(WebRtcVoiceEngineTestFake, SampleRatesViaOptions) {
EXPECT_EQ(44100u, playout_sample_rate);
}
-TEST_F(WebRtcVoiceEngineTestFake, TraceFilterViaTraceOptions) {
- EXPECT_TRUE(SetupEngineWithSendStream());
- engine_.SetLogging(rtc::LS_INFO, "");
- EXPECT_EQ(
- // Info:
- webrtc::kTraceStateInfo | webrtc::kTraceInfo |
- // Warning:
- webrtc::kTraceTerseInfo | webrtc::kTraceWarning |
- // Error:
- webrtc::kTraceError | webrtc::kTraceCritical,
- static_cast<int>(trace_wrapper_->filter_));
- // Now set it explicitly
- std::string filter =
- "tracefilter " + rtc::ToString(webrtc::kTraceDefault);
- engine_.SetLogging(rtc::LS_VERBOSE, filter.c_str());
- EXPECT_EQ(static_cast<unsigned int>(webrtc::kTraceDefault),
- trace_wrapper_->filter_);
-}
-
// Test that we can set the outgoing SSRC properly.
// SSRC is set in SetupEngine by calling AddSendStream.
TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrc) {
EXPECT_TRUE(SetupEngineWithSendStream());
- EXPECT_EQ(kSsrc1, voe_.GetLocalSSRC(voe_.GetLastChannel()));
+ EXPECT_TRUE(call_.GetAudioSendStream(kSsrc1));
}
TEST_F(WebRtcVoiceEngineTestFake, GetStats) {
@@ -2359,12 +2242,20 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStats) {
// We have added one send stream. We should see the stats we've set.
EXPECT_EQ(1u, info.senders.size());
- VerifyVoiceSenderInfo(info.senders[0]);
+ VerifyVoiceSenderInfo(info.senders[0], false);
// We have added one receive stream. We should see empty stats.
EXPECT_EQ(info.receivers.size(), 1u);
EXPECT_EQ(info.receivers[0].ssrc(), 0);
}
+ // Start sending - this affects some reported stats.
+ {
+ cricket::VoiceMediaInfo info;
+ EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
+ EXPECT_EQ(true, channel_->GetStats(&info));
+ VerifyVoiceSenderInfo(info.senders[0], true);
+ }
+
// Remove the kSsrc2 stream. No receiver stats.
{
cricket::VoiceMediaInfo info;
@@ -2391,9 +2282,10 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStats) {
// SSRC is set in SetupEngine by calling AddSendStream.
TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrcWithMultipleStreams) {
EXPECT_TRUE(SetupEngineWithSendStream());
- EXPECT_EQ(kSsrc1, voe_.GetLocalSSRC(voe_.GetLastChannel()));
- EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
- EXPECT_EQ(kSsrc1, voe_.GetLocalSSRC(voe_.GetLastChannel()));
+ EXPECT_TRUE(call_.GetAudioSendStream(kSsrc1));
+ EXPECT_TRUE(channel_->AddRecvStream(
+ cricket::StreamParams::CreateLegacy(kSsrc2)));
+ EXPECT_EQ(kSsrc1, GetRecvStreamConfig(kSsrc2).rtp.local_ssrc);
}
// Test that the local SSRC is the same on sending and receiving channels if the
@@ -2406,25 +2298,23 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrcAfterCreatingReceiveChannel) {
int receive_channel_num = voe_.GetLastChannel();
EXPECT_TRUE(channel_->AddSendStream(
cricket::StreamParams::CreateLegacy(1234)));
- int send_channel_num = voe_.GetLastChannel();
- EXPECT_EQ(1234U, voe_.GetLocalSSRC(send_channel_num));
+ EXPECT_TRUE(call_.GetAudioSendStream(1234));
EXPECT_EQ(1234U, voe_.GetLocalSSRC(receive_channel_num));
}
// Test that we can properly receive packets.
TEST_F(WebRtcVoiceEngineTestFake, Recv) {
EXPECT_TRUE(SetupEngine());
+ EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame));
int channel_num = voe_.GetLastChannel();
- EXPECT_TRUE(voe_.CheckPacket(channel_num, kPcmuFrame,
- sizeof(kPcmuFrame)));
+ EXPECT_TRUE(voe_.CheckPacket(channel_num, kPcmuFrame, sizeof(kPcmuFrame)));
}
// Test that we can properly receive packets on multiple streams.
TEST_F(WebRtcVoiceEngineTestFake, RecvWithMultipleStreams) {
- EXPECT_TRUE(SetupEngineWithSendStream());
- EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
+ EXPECT_TRUE(SetupEngine());
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
int channel_num1 = voe_.GetLastChannel();
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
@@ -2433,37 +2323,97 @@ TEST_F(WebRtcVoiceEngineTestFake, RecvWithMultipleStreams) {
int channel_num3 = voe_.GetLastChannel();
// Create packets with the right SSRCs.
char packets[4][sizeof(kPcmuFrame)];
- for (size_t i = 0; i < ARRAY_SIZE(packets); ++i) {
+ for (size_t i = 0; i < arraysize(packets); ++i) {
memcpy(packets[i], kPcmuFrame, sizeof(kPcmuFrame));
rtc::SetBE32(packets[i] + 8, static_cast<uint32_t>(i));
}
EXPECT_TRUE(voe_.CheckNoPacket(channel_num1));
EXPECT_TRUE(voe_.CheckNoPacket(channel_num2));
EXPECT_TRUE(voe_.CheckNoPacket(channel_num3));
+
DeliverPacket(packets[0], sizeof(packets[0]));
EXPECT_TRUE(voe_.CheckNoPacket(channel_num1));
EXPECT_TRUE(voe_.CheckNoPacket(channel_num2));
EXPECT_TRUE(voe_.CheckNoPacket(channel_num3));
+
DeliverPacket(packets[1], sizeof(packets[1]));
- EXPECT_TRUE(voe_.CheckPacket(channel_num1, packets[1],
- sizeof(packets[1])));
+ EXPECT_TRUE(voe_.CheckPacket(channel_num1, packets[1], sizeof(packets[1])));
EXPECT_TRUE(voe_.CheckNoPacket(channel_num2));
EXPECT_TRUE(voe_.CheckNoPacket(channel_num3));
+
DeliverPacket(packets[2], sizeof(packets[2]));
EXPECT_TRUE(voe_.CheckNoPacket(channel_num1));
- EXPECT_TRUE(voe_.CheckPacket(channel_num2, packets[2],
- sizeof(packets[2])));
+ EXPECT_TRUE(voe_.CheckPacket(channel_num2, packets[2], sizeof(packets[2])));
EXPECT_TRUE(voe_.CheckNoPacket(channel_num3));
+
DeliverPacket(packets[3], sizeof(packets[3]));
EXPECT_TRUE(voe_.CheckNoPacket(channel_num1));
EXPECT_TRUE(voe_.CheckNoPacket(channel_num2));
- EXPECT_TRUE(voe_.CheckPacket(channel_num3, packets[3],
- sizeof(packets[3])));
+ EXPECT_TRUE(voe_.CheckPacket(channel_num3, packets[3], sizeof(packets[3])));
+
EXPECT_TRUE(channel_->RemoveRecvStream(3));
EXPECT_TRUE(channel_->RemoveRecvStream(2));
EXPECT_TRUE(channel_->RemoveRecvStream(1));
}
+// Test that receiving on an unsignalled stream works (default channel will be
+// created).
+TEST_F(WebRtcVoiceEngineTestFake, RecvUnsignalled) {
+ EXPECT_TRUE(SetupEngine());
+ DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame));
+ int channel_num = voe_.GetLastChannel();
+ EXPECT_TRUE(voe_.CheckPacket(channel_num, kPcmuFrame, sizeof(kPcmuFrame)));
+}
+
+// Test that receiving on an unsignalled stream works (default channel will be
+// created), and that packets will be forwarded to the default channel
+// regardless of their SSRCs.
+TEST_F(WebRtcVoiceEngineTestFake, RecvUnsignalledWithSsrcSwitch) {
+ EXPECT_TRUE(SetupEngine());
+ char packet[sizeof(kPcmuFrame)];
+ memcpy(packet, kPcmuFrame, sizeof(kPcmuFrame));
+
+ // Note that the first unknown SSRC cannot be 0, because we only support
+ // creating receive streams for SSRC!=0.
+ DeliverPacket(packet, sizeof(packet));
+ int channel_num = voe_.GetLastChannel();
+ EXPECT_TRUE(voe_.CheckPacket(channel_num, packet, sizeof(packet)));
+ // Once we have the default channel, SSRC==0 will be ok.
+ for (uint32_t ssrc = 0; ssrc < 10; ++ssrc) {
+ rtc::SetBE32(&packet[8], ssrc);
+ DeliverPacket(packet, sizeof(packet));
+ EXPECT_TRUE(voe_.CheckPacket(channel_num, packet, sizeof(packet)));
+ }
+}
+
+// Test that a default channel is created even after a signalled stream has been
+// added, and that this stream will get any packets for unknown SSRCs.
+TEST_F(WebRtcVoiceEngineTestFake, RecvUnsignalledAfterSignalled) {
+ EXPECT_TRUE(SetupEngine());
+ char packet[sizeof(kPcmuFrame)];
+ memcpy(packet, kPcmuFrame, sizeof(kPcmuFrame));
+
+ // Add a known stream, send packet and verify we got it.
+ EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
+ int signalled_channel_num = voe_.GetLastChannel();
+ DeliverPacket(packet, sizeof(packet));
+ EXPECT_TRUE(voe_.CheckPacket(signalled_channel_num, packet, sizeof(packet)));
+
+ // Note that the first unknown SSRC cannot be 0, because we only support
+ // creating receive streams for SSRC!=0.
+ rtc::SetBE32(&packet[8], 7011);
+ DeliverPacket(packet, sizeof(packet));
+ int channel_num = voe_.GetLastChannel();
+ EXPECT_NE(channel_num, signalled_channel_num);
+ EXPECT_TRUE(voe_.CheckPacket(channel_num, packet, sizeof(packet)));
+ // Once we have the default channel, SSRC==0 will be ok.
+ for (uint32_t ssrc = 0; ssrc < 20; ssrc += 2) {
+ rtc::SetBE32(&packet[8], ssrc);
+ DeliverPacket(packet, sizeof(packet));
+ EXPECT_TRUE(voe_.CheckPacket(channel_num, packet, sizeof(packet)));
+ }
+}
+
// Test that we properly handle failures to add a receive stream.
TEST_F(WebRtcVoiceEngineTestFake, AddRecvStreamFail) {
EXPECT_TRUE(SetupEngine());
@@ -2498,7 +2448,7 @@ TEST_F(WebRtcVoiceEngineTestFake, AddRecvStreamUnsupportedCodec) {
cricket::StreamParams::CreateLegacy(kSsrc1)));
int channel_num2 = voe_.GetLastChannel();
webrtc::CodecInst gcodec;
- rtc::strcpyn(gcodec.plname, ARRAY_SIZE(gcodec.plname), "opus");
+ rtc::strcpyn(gcodec.plname, arraysize(gcodec.plname), "opus");
gcodec.plfreq = 48000;
gcodec.channels = 2;
EXPECT_EQ(-1, voe_.GetRecPayloadType(channel_num2, gcodec));
@@ -2602,10 +2552,12 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
EXPECT_TRUE(typing_detection_enabled);
EXPECT_EQ(ec_mode, webrtc::kEcConference);
EXPECT_EQ(ns_mode, webrtc::kNsHighSuppression);
+ EXPECT_EQ(50, voe_.GetNetEqCapacity());
+ EXPECT_FALSE(voe_.GetNetEqFastAccelerate());
- // Nothing set, so all ignored.
- cricket::AudioOptions options;
- ASSERT_TRUE(engine_.SetOptions(options));
+ // Nothing set in AudioOptions, so everything should be as default.
+ send_parameters_.options = cricket::AudioOptions();
+ EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
voe_.GetEcStatus(ec_enabled, ec_mode);
voe_.GetAecmMode(aecm_mode, cng_enabled);
voe_.GetAgcStatus(agc_enabled, agc_mode);
@@ -2625,20 +2577,19 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
EXPECT_TRUE(typing_detection_enabled);
EXPECT_EQ(ec_mode, webrtc::kEcConference);
EXPECT_EQ(ns_mode, webrtc::kNsHighSuppression);
- EXPECT_EQ(50, voe_.GetNetEqCapacity()); // From GetDefaultEngineOptions().
- EXPECT_FALSE(
- voe_.GetNetEqFastAccelerate()); // From GetDefaultEngineOptions().
+ EXPECT_EQ(50, voe_.GetNetEqCapacity());
+ EXPECT_FALSE(voe_.GetNetEqFastAccelerate());
// Turn echo cancellation off
- options.echo_cancellation.Set(false);
- ASSERT_TRUE(engine_.SetOptions(options));
+ send_parameters_.options.echo_cancellation = rtc::Optional<bool>(false);
+ EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
voe_.GetEcStatus(ec_enabled, ec_mode);
EXPECT_FALSE(ec_enabled);
// Turn echo cancellation back on, with settings, and make sure
// nothing else changed.
- options.echo_cancellation.Set(true);
- ASSERT_TRUE(engine_.SetOptions(options));
+ send_parameters_.options.echo_cancellation = rtc::Optional<bool>(true);
+ EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
voe_.GetEcStatus(ec_enabled, ec_mode);
voe_.GetAecmMode(aecm_mode, cng_enabled);
voe_.GetAgcStatus(agc_enabled, agc_mode);
@@ -2660,8 +2611,8 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
// Turn on delay agnostic aec and make sure nothing change w.r.t. echo
// control.
- options.delay_agnostic_aec.Set(true);
- ASSERT_TRUE(engine_.SetOptions(options));
+ send_parameters_.options.delay_agnostic_aec = rtc::Optional<bool>(true);
+ EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
voe_.GetEcStatus(ec_enabled, ec_mode);
voe_.GetAecmMode(aecm_mode, cng_enabled);
EXPECT_TRUE(ec_enabled);
@@ -2669,41 +2620,41 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
EXPECT_EQ(ec_mode, webrtc::kEcConference);
// Turn off echo cancellation and delay agnostic aec.
- options.delay_agnostic_aec.Set(false);
- options.extended_filter_aec.Set(false);
- options.echo_cancellation.Set(false);
- ASSERT_TRUE(engine_.SetOptions(options));
+ send_parameters_.options.delay_agnostic_aec = rtc::Optional<bool>(false);
+ send_parameters_.options.extended_filter_aec = rtc::Optional<bool>(false);
+ send_parameters_.options.echo_cancellation = rtc::Optional<bool>(false);
+ EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
voe_.GetEcStatus(ec_enabled, ec_mode);
EXPECT_FALSE(ec_enabled);
// Turning delay agnostic aec back on should also turn on echo cancellation.
- options.delay_agnostic_aec.Set(true);
- ASSERT_TRUE(engine_.SetOptions(options));
+ send_parameters_.options.delay_agnostic_aec = rtc::Optional<bool>(true);
+ EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
voe_.GetEcStatus(ec_enabled, ec_mode);
EXPECT_TRUE(ec_enabled);
EXPECT_TRUE(voe_.ec_metrics_enabled());
EXPECT_EQ(ec_mode, webrtc::kEcConference);
// Turn off AGC
- options.auto_gain_control.Set(false);
- ASSERT_TRUE(engine_.SetOptions(options));
+ send_parameters_.options.auto_gain_control = rtc::Optional<bool>(false);
+ EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
voe_.GetAgcStatus(agc_enabled, agc_mode);
EXPECT_FALSE(agc_enabled);
// Turn AGC back on
- options.auto_gain_control.Set(true);
- options.adjust_agc_delta.Clear();
- ASSERT_TRUE(engine_.SetOptions(options));
+ send_parameters_.options.auto_gain_control = rtc::Optional<bool>(true);
+ send_parameters_.options.adjust_agc_delta = rtc::Optional<int>();
+ EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
voe_.GetAgcStatus(agc_enabled, agc_mode);
EXPECT_TRUE(agc_enabled);
voe_.GetAgcConfig(agc_config);
EXPECT_EQ(0, agc_config.targetLeveldBOv);
// Turn off other options (and stereo swapping on).
- options.noise_suppression.Set(false);
- options.highpass_filter.Set(false);
- options.typing_detection.Set(false);
- options.stereo_swapping.Set(true);
- ASSERT_TRUE(engine_.SetOptions(options));
+ send_parameters_.options.noise_suppression = rtc::Optional<bool>(false);
+ send_parameters_.options.highpass_filter = rtc::Optional<bool>(false);
+ send_parameters_.options.typing_detection = rtc::Optional<bool>(false);
+ send_parameters_.options.stereo_swapping = rtc::Optional<bool>(true);
+ EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
voe_.GetNsStatus(ns_enabled, ns_mode);
highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
@@ -2714,7 +2665,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
EXPECT_TRUE(stereo_swapping_enabled);
// Set options again to ensure it has no impact.
- ASSERT_TRUE(engine_.SetOptions(options));
+ EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
voe_.GetEcStatus(ec_enabled, ec_mode);
voe_.GetNsStatus(ns_enabled, ns_mode);
EXPECT_TRUE(ec_enabled);
@@ -2785,9 +2736,9 @@ TEST_F(WebRtcVoiceEngineTestFake, SetOptionOverridesViaChannels) {
// AEC and AGC and NS
cricket::AudioSendParameters parameters_options_all = send_parameters_;
- parameters_options_all.options.echo_cancellation.Set(true);
- parameters_options_all.options.auto_gain_control.Set(true);
- parameters_options_all.options.noise_suppression.Set(true);
+ parameters_options_all.options.echo_cancellation = rtc::Optional<bool>(true);
+ parameters_options_all.options.auto_gain_control = rtc::Optional<bool>(true);
+ parameters_options_all.options.noise_suppression = rtc::Optional<bool>(true);
ASSERT_TRUE(channel1->SetSendParameters(parameters_options_all));
EXPECT_EQ(parameters_options_all.options, channel1->options());
ASSERT_TRUE(channel2->SetSendParameters(parameters_options_all));
@@ -2795,24 +2746,26 @@ TEST_F(WebRtcVoiceEngineTestFake, SetOptionOverridesViaChannels) {
// unset NS
cricket::AudioSendParameters parameters_options_no_ns = send_parameters_;
- parameters_options_no_ns.options.noise_suppression.Set(false);
+ parameters_options_no_ns.options.noise_suppression =
+ rtc::Optional<bool>(false);
ASSERT_TRUE(channel1->SetSendParameters(parameters_options_no_ns));
cricket::AudioOptions expected_options = parameters_options_all.options;
- expected_options.echo_cancellation.Set(true);
- expected_options.auto_gain_control.Set(true);
- expected_options.noise_suppression.Set(false);
+ expected_options.echo_cancellation = rtc::Optional<bool>(true);
+ expected_options.auto_gain_control = rtc::Optional<bool>(true);
+ expected_options.noise_suppression = rtc::Optional<bool>(false);
EXPECT_EQ(expected_options, channel1->options());
// unset AGC
cricket::AudioSendParameters parameters_options_no_agc = send_parameters_;
- parameters_options_no_agc.options.auto_gain_control.Set(false);
+ parameters_options_no_agc.options.auto_gain_control =
+ rtc::Optional<bool>(false);
ASSERT_TRUE(channel2->SetSendParameters(parameters_options_no_agc));
- expected_options.echo_cancellation.Set(true);
- expected_options.auto_gain_control.Set(false);
- expected_options.noise_suppression.Set(true);
+ expected_options.echo_cancellation = rtc::Optional<bool>(true);
+ expected_options.auto_gain_control = rtc::Optional<bool>(false);
+ expected_options.noise_suppression = rtc::Optional<bool>(true);
EXPECT_EQ(expected_options, channel2->options());
- ASSERT_TRUE(engine_.SetOptions(parameters_options_all.options));
+ ASSERT_TRUE(channel_->SetSendParameters(parameters_options_all));
bool ec_enabled;
webrtc::EcModes ec_mode;
bool agc_enabled;
@@ -2834,14 +2787,6 @@ TEST_F(WebRtcVoiceEngineTestFake, SetOptionOverridesViaChannels) {
EXPECT_TRUE(agc_enabled);
EXPECT_FALSE(ns_enabled);
- channel1->SetSend(cricket::SEND_NOTHING);
- voe_.GetEcStatus(ec_enabled, ec_mode);
- voe_.GetAgcStatus(agc_enabled, agc_mode);
- voe_.GetNsStatus(ns_enabled, ns_mode);
- EXPECT_TRUE(ec_enabled);
- EXPECT_TRUE(agc_enabled);
- EXPECT_TRUE(ns_enabled);
-
channel2->SetSend(cricket::SEND_MICROPHONE);
voe_.GetEcStatus(ec_enabled, ec_mode);
voe_.GetAgcStatus(agc_enabled, agc_mode);
@@ -2850,25 +2795,19 @@ TEST_F(WebRtcVoiceEngineTestFake, SetOptionOverridesViaChannels) {
EXPECT_FALSE(agc_enabled);
EXPECT_TRUE(ns_enabled);
- channel2->SetSend(cricket::SEND_NOTHING);
- voe_.GetEcStatus(ec_enabled, ec_mode);
- voe_.GetAgcStatus(agc_enabled, agc_mode);
- voe_.GetNsStatus(ns_enabled, ns_mode);
- EXPECT_TRUE(ec_enabled);
- EXPECT_TRUE(agc_enabled);
- EXPECT_TRUE(ns_enabled);
-
// Make sure settings take effect while we are sending.
- ASSERT_TRUE(engine_.SetOptions(parameters_options_all.options));
+ ASSERT_TRUE(channel_->SetSendParameters(parameters_options_all));
cricket::AudioSendParameters parameters_options_no_agc_nor_ns =
send_parameters_;
- parameters_options_no_agc_nor_ns.options.auto_gain_control.Set(false);
- parameters_options_no_agc_nor_ns.options.noise_suppression.Set(false);
+ parameters_options_no_agc_nor_ns.options.auto_gain_control =
+ rtc::Optional<bool>(false);
+ parameters_options_no_agc_nor_ns.options.noise_suppression =
+ rtc::Optional<bool>(false);
channel2->SetSend(cricket::SEND_MICROPHONE);
channel2->SetSendParameters(parameters_options_no_agc_nor_ns);
- expected_options.echo_cancellation.Set(true);
- expected_options.auto_gain_control.Set(false);
- expected_options.noise_suppression.Set(false);
+ expected_options.echo_cancellation = rtc::Optional<bool>(true);
+ expected_options.auto_gain_control = rtc::Optional<bool>(false);
+ expected_options.noise_suppression = rtc::Optional<bool>(false);
EXPECT_EQ(expected_options, channel2->options());
voe_.GetEcStatus(ec_enabled, ec_mode);
voe_.GetAgcStatus(agc_enabled, agc_mode);
@@ -2887,13 +2826,13 @@ TEST_F(WebRtcVoiceEngineTestFake, TestSetDscpOptions) {
new cricket::FakeNetworkInterface);
channel->SetInterface(network_interface.get());
cricket::AudioSendParameters parameters = send_parameters_;
- parameters.options.dscp.Set(true);
+ parameters.options.dscp = rtc::Optional<bool>(true);
EXPECT_TRUE(channel->SetSendParameters(parameters));
EXPECT_EQ(rtc::DSCP_EF, network_interface->dscp());
// Verify previous value is not modified if dscp option is not set.
EXPECT_TRUE(channel->SetSendParameters(send_parameters_));
EXPECT_EQ(rtc::DSCP_EF, network_interface->dscp());
- parameters.options.dscp.Set(false);
+ parameters.options.dscp = rtc::Optional<bool>(false);
EXPECT_TRUE(channel->SetSendParameters(parameters));
EXPECT_EQ(rtc::DSCP_DEFAULT, network_interface->dscp());
}
@@ -3002,7 +2941,7 @@ TEST_F(WebRtcVoiceEngineTestFake, CanChangeCombinedBweOption) {
}
// Enable combined BWE option - now it should be set up.
- send_parameters_.options.combined_audio_video_bwe.Set(true);
+ send_parameters_.options.combined_audio_video_bwe = rtc::Optional<bool>(true);
EXPECT_TRUE(media_channel->SetSendParameters(send_parameters_));
for (uint32_t ssrc : ssrcs) {
const auto* s = call_.GetAudioReceiveStream(ssrc);
@@ -3011,7 +2950,8 @@ TEST_F(WebRtcVoiceEngineTestFake, CanChangeCombinedBweOption) {
}
// Disable combined BWE option - should be disabled again.
- send_parameters_.options.combined_audio_video_bwe.Set(false);
+ send_parameters_.options.combined_audio_video_bwe =
+ rtc::Optional<bool>(false);
EXPECT_TRUE(media_channel->SetSendParameters(send_parameters_));
for (uint32_t ssrc : ssrcs) {
const auto* s = call_.GetAudioReceiveStream(ssrc);
@@ -3028,18 +2968,19 @@ TEST_F(WebRtcVoiceEngineTestFake, ConfigureCombinedBweForNewRecvStreams) {
EXPECT_TRUE(SetupEngineWithSendStream());
cricket::WebRtcVoiceMediaChannel* media_channel =
static_cast<cricket::WebRtcVoiceMediaChannel*>(channel_);
- send_parameters_.options.combined_audio_video_bwe.Set(true);
+ send_parameters_.options.combined_audio_video_bwe = rtc::Optional<bool>(true);
EXPECT_TRUE(media_channel->SetSendParameters(send_parameters_));
- static const uint32_t kSsrcs[] = {1, 2, 3, 4};
- for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs); ++i) {
+ for (uint32_t ssrc : kSsrcs4) {
EXPECT_TRUE(media_channel->AddRecvStream(
- cricket::StreamParams::CreateLegacy(kSsrcs[i])));
- EXPECT_NE(nullptr, call_.GetAudioReceiveStream(kSsrcs[i]));
+ cricket::StreamParams::CreateLegacy(ssrc)));
+ EXPECT_NE(nullptr, call_.GetAudioReceiveStream(ssrc));
}
- EXPECT_EQ(ARRAY_SIZE(kSsrcs), call_.GetAudioReceiveStreams().size());
+ EXPECT_EQ(arraysize(kSsrcs4), call_.GetAudioReceiveStreams().size());
}
+// TODO(solenberg): Remove, once recv streams are configured through Call.
+// (This is then covered by TestSetRecvRtpHeaderExtensions.)
TEST_F(WebRtcVoiceEngineTestFake, ConfiguresAudioReceiveStreamRtpExtensions) {
// Test that setting the header extensions results in the expected state
// changes on an associated Call.
@@ -3050,7 +2991,7 @@ TEST_F(WebRtcVoiceEngineTestFake, ConfiguresAudioReceiveStreamRtpExtensions) {
EXPECT_TRUE(SetupEngineWithSendStream());
cricket::WebRtcVoiceMediaChannel* media_channel =
static_cast<cricket::WebRtcVoiceMediaChannel*>(channel_);
- send_parameters_.options.combined_audio_video_bwe.Set(true);
+ send_parameters_.options.combined_audio_video_bwe = rtc::Optional<bool>(true);
EXPECT_TRUE(media_channel->SetSendParameters(send_parameters_));
for (uint32_t ssrc : ssrcs) {
EXPECT_TRUE(media_channel->AddRecvStream(
@@ -3066,17 +3007,17 @@ TEST_F(WebRtcVoiceEngineTestFake, ConfiguresAudioReceiveStreamRtpExtensions) {
}
// Set up receive extensions.
- const auto& e_exts = engine_.rtp_header_extensions();
+ cricket::RtpCapabilities capabilities = engine_.GetCapabilities();
cricket::AudioRecvParameters recv_parameters;
- recv_parameters.extensions = e_exts;
+ recv_parameters.extensions = capabilities.header_extensions;
channel_->SetRecvParameters(recv_parameters);
EXPECT_EQ(2, call_.GetAudioReceiveStreams().size());
for (uint32_t ssrc : ssrcs) {
const auto* s = call_.GetAudioReceiveStream(ssrc);
EXPECT_NE(nullptr, s);
const auto& s_exts = s->GetConfig().rtp.extensions;
- EXPECT_EQ(e_exts.size(), s_exts.size());
- for (const auto& e_ext : e_exts) {
+ EXPECT_EQ(capabilities.header_extensions.size(), s_exts.size());
+ for (const auto& e_ext : capabilities.header_extensions) {
for (const auto& s_ext : s_exts) {
if (e_ext.id == s_ext.id) {
EXPECT_EQ(e_ext.uri, s_ext.name);
@@ -3109,7 +3050,7 @@ TEST_F(WebRtcVoiceEngineTestFake, DeliverAudioPacket_Call) {
EXPECT_TRUE(SetupEngineWithSendStream());
cricket::WebRtcVoiceMediaChannel* media_channel =
static_cast<cricket::WebRtcVoiceMediaChannel*>(channel_);
- send_parameters_.options.combined_audio_video_bwe.Set(true);
+ send_parameters_.options.combined_audio_video_bwe = rtc::Optional<bool>(true);
EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
EXPECT_TRUE(media_channel->AddRecvStream(
cricket::StreamParams::CreateLegacy(kAudioSsrc)));
@@ -3164,18 +3105,6 @@ TEST_F(WebRtcVoiceEngineTestFake, AssociateChannelResetUponDeleteChannnel) {
EXPECT_EQ(voe_.GetAssociateSendChannel(recv_ch), -1);
}
-// Tests for the actual WebRtc VoE library.
-
-TEST(WebRtcVoiceEngineTest, TestDefaultOptionsBeforeInit) {
- cricket::WebRtcVoiceEngine engine;
- cricket::AudioOptions options = engine.GetOptions();
- // The default options should have at least a few things set. We purposefully
- // don't check the option values here, though.
- EXPECT_TRUE(options.echo_cancellation.IsSet());
- EXPECT_TRUE(options.auto_gain_control.IsSet());
- EXPECT_TRUE(options.noise_suppression.IsSet());
-}
-
// Tests that the library initializes and shuts down properly.
TEST(WebRtcVoiceEngineTest, StartupShutdown) {
cricket::WebRtcVoiceEngine engine;
@@ -3195,54 +3124,60 @@ TEST(WebRtcVoiceEngineTest, StartupShutdown) {
// Tests that the library is configured with the codecs we want.
TEST(WebRtcVoiceEngineTest, HasCorrectCodecs) {
- cricket::WebRtcVoiceEngine engine;
// Check codecs by name.
- EXPECT_TRUE(engine.FindCodec(
- cricket::AudioCodec(96, "OPUS", 48000, 0, 2, 0)));
- EXPECT_TRUE(engine.FindCodec(
- cricket::AudioCodec(96, "ISAC", 16000, 0, 1, 0)));
- EXPECT_TRUE(engine.FindCodec(
- cricket::AudioCodec(96, "ISAC", 32000, 0, 1, 0)));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(96, "OPUS", 48000, 0, 2, 0), nullptr));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(96, "ISAC", 16000, 0, 1, 0), nullptr));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(96, "ISAC", 32000, 0, 1, 0), nullptr));
// Check that name matching is case-insensitive.
- EXPECT_TRUE(engine.FindCodec(
- cricket::AudioCodec(96, "ILBC", 8000, 0, 1, 0)));
- EXPECT_TRUE(engine.FindCodec(
- cricket::AudioCodec(96, "iLBC", 8000, 0, 1, 0)));
- EXPECT_TRUE(engine.FindCodec(
- cricket::AudioCodec(96, "PCMU", 8000, 0, 1, 0)));
- EXPECT_TRUE(engine.FindCodec(
- cricket::AudioCodec(96, "PCMA", 8000, 0, 1, 0)));
- EXPECT_TRUE(engine.FindCodec(
- cricket::AudioCodec(96, "G722", 8000, 0, 1, 0)));
- EXPECT_TRUE(engine.FindCodec(
- cricket::AudioCodec(96, "red", 8000, 0, 1, 0)));
- EXPECT_TRUE(engine.FindCodec(
- cricket::AudioCodec(96, "CN", 32000, 0, 1, 0)));
- EXPECT_TRUE(engine.FindCodec(
- cricket::AudioCodec(96, "CN", 16000, 0, 1, 0)));
- EXPECT_TRUE(engine.FindCodec(
- cricket::AudioCodec(96, "CN", 8000, 0, 1, 0)));
- EXPECT_TRUE(engine.FindCodec(
- cricket::AudioCodec(96, "telephone-event", 8000, 0, 1, 0)));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(96, "ILBC", 8000, 0, 1, 0), nullptr));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(96, "iLBC", 8000, 0, 1, 0), nullptr));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(96, "PCMU", 8000, 0, 1, 0), nullptr));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(96, "PCMA", 8000, 0, 1, 0), nullptr));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(96, "G722", 8000, 0, 1, 0), nullptr));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(96, "red", 8000, 0, 1, 0), nullptr));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(96, "CN", 32000, 0, 1, 0), nullptr));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(96, "CN", 16000, 0, 1, 0), nullptr));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(96, "CN", 8000, 0, 1, 0), nullptr));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(96, "telephone-event", 8000, 0, 1, 0), nullptr));
// Check codecs with an id by id.
- EXPECT_TRUE(engine.FindCodec(
- cricket::AudioCodec(0, "", 8000, 0, 1, 0))); // PCMU
- EXPECT_TRUE(engine.FindCodec(
- cricket::AudioCodec(8, "", 8000, 0, 1, 0))); // PCMA
- EXPECT_TRUE(engine.FindCodec(
- cricket::AudioCodec(9, "", 8000, 0, 1, 0))); // G722
- EXPECT_TRUE(engine.FindCodec(
- cricket::AudioCodec(13, "", 8000, 0, 1, 0))); // CN
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(0, "", 8000, 0, 1, 0), nullptr)); // PCMU
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(8, "", 8000, 0, 1, 0), nullptr)); // PCMA
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(9, "", 8000, 0, 1, 0), nullptr)); // G722
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(13, "", 8000, 0, 1, 0), nullptr)); // CN
// Check sample/bitrate matching.
- EXPECT_TRUE(engine.FindCodec(
- cricket::AudioCodec(0, "PCMU", 8000, 64000, 1, 0)));
+ EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(0, "PCMU", 8000, 64000, 1, 0), nullptr));
// Check that bad codecs fail.
- EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(99, "ABCD", 0, 0, 1, 0)));
- EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(88, "", 0, 0, 1, 0)));
- EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(0, "", 0, 0, 2, 0)));
- EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(0, "", 5000, 0, 1, 0)));
- EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(0, "", 0, 5000, 1, 0)));
+ EXPECT_FALSE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(99, "ABCD", 0, 0, 1, 0), nullptr));
+ EXPECT_FALSE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(88, "", 0, 0, 1, 0), nullptr));
+ EXPECT_FALSE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(0, "", 0, 0, 2, 0), nullptr));
+ EXPECT_FALSE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(0, "", 5000, 0, 1, 0), nullptr));
+ EXPECT_FALSE(cricket::WebRtcVoiceEngine::ToCodecInst(
+ cricket::AudioCodec(0, "", 0, 5000, 1, 0), nullptr));
+
// Verify the payload id of common audio codecs, including CN, ISAC, and G722.
+ cricket::WebRtcVoiceEngine engine;
for (std::vector<cricket::AudioCodec>::const_iterator it =
engine.codecs().begin(); it != engine.codecs().end(); ++it) {
if (it->name == "CN" && it->clockrate == 16000) {
@@ -3269,7 +3204,6 @@ TEST(WebRtcVoiceEngineTest, HasCorrectCodecs) {
EXPECT_EQ("1", it->params.find("useinbandfec")->second);
}
}
-
engine.Terminate();
}
@@ -3282,7 +3216,7 @@ TEST(WebRtcVoiceEngineTest, Has32Channels) {
cricket::VoiceMediaChannel* channels[32];
int num_channels = 0;
- while (num_channels < ARRAY_SIZE(channels)) {
+ while (num_channels < arraysize(channels)) {
cricket::VoiceMediaChannel* channel =
engine.CreateChannel(call.get(), cricket::AudioOptions());
if (!channel)
@@ -3290,7 +3224,7 @@ TEST(WebRtcVoiceEngineTest, Has32Channels) {
channels[num_channels++] = channel;
}
- int expected = ARRAY_SIZE(channels);
+ int expected = arraysize(channels);
EXPECT_EQ(expected, num_channels);
while (num_channels > 0) {