Implement AudioSendStream::GetStats().
BUG=webrtc:4690 Review URL: https://codereview.webrtc.org/1414743004 Cr-Commit-Position: refs/heads/master@{#10424}
This commit is contained in:
parent
2a0a2a410f
commit
85a0496b8c
@ -39,8 +39,9 @@ FakeAudioSendStream::FakeAudioSendStream(
|
||||
RTC_DCHECK(config.voe_channel_id != -1);
|
||||
}
|
||||
|
||||
webrtc::AudioSendStream::Stats FakeAudioSendStream::GetStats() const {
|
||||
return webrtc::AudioSendStream::Stats();
|
||||
void FakeAudioSendStream::SetStats(
|
||||
const webrtc::AudioSendStream::Stats& stats) {
|
||||
stats_ = stats;
|
||||
}
|
||||
|
||||
const webrtc::AudioSendStream::Config&
|
||||
@ -48,6 +49,10 @@ const webrtc::AudioSendStream::Config&
|
||||
return config_;
|
||||
}
|
||||
|
||||
webrtc::AudioSendStream::Stats FakeAudioSendStream::GetStats() const {
|
||||
return stats_;
|
||||
}
|
||||
|
||||
FakeAudioReceiveStream::FakeAudioReceiveStream(
|
||||
const webrtc::AudioReceiveStream::Config& config)
|
||||
: config_(config), received_packets_(0) {
|
||||
@ -68,6 +73,10 @@ void FakeAudioReceiveStream::IncrementReceivedPackets() {
|
||||
received_packets_++;
|
||||
}
|
||||
|
||||
webrtc::AudioReceiveStream::Stats FakeAudioReceiveStream::GetStats() const {
|
||||
return stats_;
|
||||
}
|
||||
|
||||
FakeVideoSendStream::FakeVideoSendStream(
|
||||
const webrtc::VideoSendStream::Config& config,
|
||||
const webrtc::VideoEncoderConfig& encoder_config)
|
||||
|
||||
@ -53,10 +53,8 @@ class FakeAudioSendStream : public webrtc::AudioSendStream {
|
||||
explicit FakeAudioSendStream(
|
||||
const webrtc::AudioSendStream::Config& config);
|
||||
|
||||
// webrtc::AudioSendStream implementation.
|
||||
webrtc::AudioSendStream::Stats GetStats() const override;
|
||||
|
||||
const webrtc::AudioSendStream::Config& GetConfig() const;
|
||||
void SetStats(const webrtc::AudioSendStream::Stats& stats);
|
||||
|
||||
private:
|
||||
// webrtc::SendStream implementation.
|
||||
@ -67,7 +65,11 @@ class FakeAudioSendStream : public webrtc::AudioSendStream {
|
||||
return true;
|
||||
}
|
||||
|
||||
// webrtc::AudioSendStream implementation.
|
||||
webrtc::AudioSendStream::Stats GetStats() const override;
|
||||
|
||||
webrtc::AudioSendStream::Config config_;
|
||||
webrtc::AudioSendStream::Stats stats_;
|
||||
};
|
||||
|
||||
class FakeAudioReceiveStream : public webrtc::AudioReceiveStream {
|
||||
@ -95,9 +97,7 @@ class FakeAudioReceiveStream : public webrtc::AudioReceiveStream {
|
||||
}
|
||||
|
||||
// webrtc::AudioReceiveStream implementation.
|
||||
webrtc::AudioReceiveStream::Stats GetStats() const override {
|
||||
return stats_;
|
||||
}
|
||||
webrtc::AudioReceiveStream::Stats GetStats() const override;
|
||||
|
||||
webrtc::AudioReceiveStream::Config config_;
|
||||
webrtc::AudioReceiveStream::Stats stats_;
|
||||
|
||||
@ -45,11 +45,6 @@
|
||||
|
||||
namespace cricket {
|
||||
|
||||
// Function returning stats will return these values
|
||||
// for all values based on type.
|
||||
const int kIntStatValue = 123;
|
||||
const float kFractionLostStatValue = 0.5;
|
||||
|
||||
static const char kFakeDefaultDeviceName[] = "Fake Default";
|
||||
static const int kFakeDefaultDeviceId = -1;
|
||||
static const char kFakeDeviceName[] = "Fake Device";
|
||||
@ -268,6 +263,8 @@ class FakeWebRtcVoiceEngine
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
@ -279,6 +276,9 @@ class FakeWebRtcVoiceEngine
|
||||
return -1;
|
||||
}
|
||||
int GetNumChannels() const { return static_cast<int>(channels_.size()); }
|
||||
uint32_t GetLocalSSRC(int channel) {
|
||||
return channels_[channel]->send_ssrc;
|
||||
}
|
||||
bool GetPlayout(int channel) {
|
||||
return channels_[channel]->playout;
|
||||
}
|
||||
@ -727,11 +727,7 @@ class FakeWebRtcVoiceEngine
|
||||
channels_[channel]->send_ssrc = ssrc;
|
||||
return 0;
|
||||
}
|
||||
WEBRTC_FUNC(GetLocalSSRC, (int channel, unsigned int& ssrc)) {
|
||||
WEBRTC_CHECK_CHANNEL(channel);
|
||||
ssrc = channels_[channel]->send_ssrc;
|
||||
return 0;
|
||||
}
|
||||
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)) {
|
||||
@ -773,39 +769,12 @@ class FakeWebRtcVoiceEngine
|
||||
unsigned int& playoutTimestamp,
|
||||
unsigned int* jitter,
|
||||
unsigned short* fractionLost));
|
||||
WEBRTC_FUNC(GetRemoteRTCPReportBlocks,
|
||||
(int channel, std::vector<webrtc::ReportBlock>* receive_blocks)) {
|
||||
WEBRTC_CHECK_CHANNEL(channel);
|
||||
webrtc::ReportBlock block;
|
||||
block.source_SSRC = channels_[channel]->send_ssrc;
|
||||
webrtc::CodecInst send_codec = channels_[channel]->send_codec;
|
||||
if (send_codec.pltype >= 0) {
|
||||
block.fraction_lost = (unsigned char)(kFractionLostStatValue * 256);
|
||||
if (send_codec.plfreq / 1000 > 0) {
|
||||
block.interarrival_jitter = kIntStatValue * (send_codec.plfreq / 1000);
|
||||
}
|
||||
block.cumulative_num_packets_lost = kIntStatValue;
|
||||
block.extended_highest_sequence_number = kIntStatValue;
|
||||
receive_blocks->push_back(block);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
WEBRTC_STUB(GetRemoteRTCPReportBlocks,
|
||||
(int channel, std::vector<webrtc::ReportBlock>* receive_blocks));
|
||||
WEBRTC_STUB(GetRTPStatistics, (int channel, unsigned int& averageJitterMs,
|
||||
unsigned int& maxJitterMs,
|
||||
unsigned int& discardedPackets));
|
||||
WEBRTC_FUNC(GetRTCPStatistics, (int channel, webrtc::CallStatistics& stats)) {
|
||||
WEBRTC_CHECK_CHANNEL(channel);
|
||||
stats.fractionLost = static_cast<int16_t>(kIntStatValue);
|
||||
stats.cumulativeLost = kIntStatValue;
|
||||
stats.extendedMax = kIntStatValue;
|
||||
stats.jitterSamples = kIntStatValue;
|
||||
stats.rttMs = kIntStatValue;
|
||||
stats.bytesSent = kIntStatValue;
|
||||
stats.packetsSent = kIntStatValue;
|
||||
stats.bytesReceived = kIntStatValue;
|
||||
stats.packetsReceived = kIntStatValue;
|
||||
return 0;
|
||||
}
|
||||
WEBRTC_STUB(GetRTCPStatistics, (int channel, webrtc::CallStatistics& stats));
|
||||
WEBRTC_FUNC(SetREDStatus, (int channel, bool enable, int redPayloadtype)) {
|
||||
return SetFECStatus(channel, enable, redPayloadtype);
|
||||
}
|
||||
@ -931,10 +900,7 @@ class FakeWebRtcVoiceEngine
|
||||
ec_metrics_enabled_ = enable;
|
||||
return 0;
|
||||
}
|
||||
WEBRTC_FUNC(GetEcMetricsStatus, (bool& enabled)) {
|
||||
enabled = ec_metrics_enabled_;
|
||||
return 0;
|
||||
}
|
||||
WEBRTC_STUB(GetEcMetricsStatus, (bool& enabled));
|
||||
WEBRTC_STUB(GetEchoMetrics, (int& ERL, int& ERLE, int& RERL, int& A_NLP));
|
||||
WEBRTC_STUB(GetEcDelayMetrics, (int& delay_median, int& delay_std,
|
||||
float& fraction_poor_delays));
|
||||
|
||||
@ -1321,7 +1321,11 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
|
||||
: channel_(ch),
|
||||
voe_audio_transport_(voe_audio_transport),
|
||||
call_(call) {
|
||||
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;
|
||||
@ -1329,6 +1333,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
|
||||
RTC_DCHECK(stream_);
|
||||
}
|
||||
~WebRtcAudioSendStream() override {
|
||||
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
|
||||
Stop();
|
||||
call_->DestroyAudioSendStream(stream_);
|
||||
}
|
||||
@ -1338,7 +1343,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
|
||||
// This method is called on the libjingle worker thread.
|
||||
// TODO(xians): Make sure Start() is called only once.
|
||||
void Start(AudioRenderer* renderer) {
|
||||
rtc::CritScope lock(&lock_);
|
||||
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(renderer);
|
||||
if (renderer_) {
|
||||
RTC_DCHECK(renderer_ == renderer);
|
||||
@ -1348,11 +1353,16 @@ 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::CritScope lock(&lock_);
|
||||
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
|
||||
if (renderer_) {
|
||||
renderer_->SetSink(nullptr);
|
||||
renderer_ = nullptr;
|
||||
@ -1366,6 +1376,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
|
||||
int sample_rate,
|
||||
int number_of_channels,
|
||||
size_t number_of_frames) override {
|
||||
RTC_DCHECK(audio_capture_thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(voe_audio_transport_);
|
||||
voe_audio_transport_->OnData(channel_,
|
||||
audio_data,
|
||||
@ -1378,16 +1389,21 @@ 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::CritScope lock(&lock_);
|
||||
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
|
||||
// Set |renderer_| to nullptr to make sure no more callback will get into
|
||||
// the renderer.
|
||||
renderer_ = nullptr;
|
||||
}
|
||||
|
||||
// Accessor to the VoE channel ID.
|
||||
int channel() const { return channel_; }
|
||||
int channel() const {
|
||||
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
|
||||
return channel_;
|
||||
}
|
||||
|
||||
private:
|
||||
rtc::ThreadChecker signal_thread_checker_;
|
||||
rtc::ThreadChecker audio_capture_thread_checker_;
|
||||
const int channel_ = -1;
|
||||
webrtc::AudioTransport* const voe_audio_transport_ = nullptr;
|
||||
webrtc::Call* call_ = nullptr;
|
||||
@ -1398,9 +1414,6 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
|
||||
// goes away.
|
||||
AudioRenderer* renderer_ = nullptr;
|
||||
|
||||
// Protects |renderer_| in Start(), Stop() and OnClose().
|
||||
rtc::CriticalSection lock_;
|
||||
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream);
|
||||
};
|
||||
|
||||
@ -1433,7 +1446,6 @@ WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine,
|
||||
desired_send_(SEND_NOTHING),
|
||||
send_(SEND_NOTHING),
|
||||
call_(call) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel";
|
||||
RTC_DCHECK(nullptr != call);
|
||||
engine->RegisterChannel(this);
|
||||
@ -2618,109 +2630,36 @@ bool WebRtcVoiceMediaChannel::SetSendBitrateInternal(int bps) {
|
||||
|
||||
bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(info);
|
||||
|
||||
bool echo_metrics_on = false;
|
||||
// These can take on valid negative values, so use the lowest possible level
|
||||
// as default rather than -1.
|
||||
int echo_return_loss = -100;
|
||||
int echo_return_loss_enhancement = -100;
|
||||
// These can also be negative, but in practice -1 is only used to signal
|
||||
// insufficient data, since the resolution is limited to multiples of 4 ms.
|
||||
int echo_delay_median_ms = -1;
|
||||
int echo_delay_std_ms = -1;
|
||||
if (engine()->voe()->processing()->GetEcMetricsStatus(
|
||||
echo_metrics_on) != -1 && echo_metrics_on) {
|
||||
// TODO(ajm): we may want to use VoECallReport::GetEchoMetricsSummary
|
||||
// here, but it appears to be unsuitable currently. Revisit after this is
|
||||
// investigated: http://b/issue?id=5666755
|
||||
int erl, erle, rerl, anlp;
|
||||
if (engine()->voe()->processing()->GetEchoMetrics(
|
||||
erl, erle, rerl, anlp) != -1) {
|
||||
echo_return_loss = erl;
|
||||
echo_return_loss_enhancement = erle;
|
||||
}
|
||||
|
||||
int median, std;
|
||||
float dummy;
|
||||
if (engine()->voe()->processing()->GetEcDelayMetrics(
|
||||
median, std, dummy) != -1) {
|
||||
echo_delay_median_ms = median;
|
||||
echo_delay_std_ms = std;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& ch : send_streams_) {
|
||||
const int channel = ch.second->channel();
|
||||
|
||||
// Fill in the sender info, based on what we know, and what the
|
||||
// remote side told us it got from its RTCP report.
|
||||
// Get SSRC and stats for each sender.
|
||||
RTC_DCHECK(info->senders.size() == 0);
|
||||
for (const auto& stream : send_streams_) {
|
||||
webrtc::AudioSendStream::Stats stats = stream.second->GetStats();
|
||||
VoiceSenderInfo sinfo;
|
||||
|
||||
webrtc::CallStatistics cs = {0};
|
||||
unsigned int ssrc = 0;
|
||||
if (engine()->voe()->rtp()->GetRTCPStatistics(channel, cs) == -1 ||
|
||||
engine()->voe()->rtp()->GetLocalSSRC(channel, ssrc) == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sinfo.add_ssrc(ssrc);
|
||||
sinfo.codec_name = send_codec_.get() ? send_codec_->plname : "";
|
||||
sinfo.bytes_sent = cs.bytesSent;
|
||||
sinfo.packets_sent = cs.packetsSent;
|
||||
// RTT isn't known until a RTCP report is received. Until then, VoiceEngine
|
||||
// returns 0 to indicate an error value.
|
||||
sinfo.rtt_ms = (cs.rttMs > 0) ? cs.rttMs : -1;
|
||||
|
||||
// Get data from the last remote RTCP report. Use default values if no data
|
||||
// available.
|
||||
sinfo.fraction_lost = -1.0;
|
||||
sinfo.jitter_ms = -1;
|
||||
sinfo.packets_lost = -1;
|
||||
sinfo.ext_seqnum = -1;
|
||||
std::vector<webrtc::ReportBlock> receive_blocks;
|
||||
webrtc::CodecInst codec = {0};
|
||||
if (engine()->voe()->rtp()->GetRemoteRTCPReportBlocks(
|
||||
channel, &receive_blocks) != -1 &&
|
||||
engine()->voe()->codec()->GetSendCodec(channel, codec) != -1) {
|
||||
for (const webrtc::ReportBlock& block : receive_blocks) {
|
||||
// Lookup report for send ssrc only.
|
||||
if (block.source_SSRC == sinfo.ssrc()) {
|
||||
// Convert Q8 to floating point.
|
||||
sinfo.fraction_lost = static_cast<float>(block.fraction_lost) / 256;
|
||||
// Convert samples to milliseconds.
|
||||
if (codec.plfreq / 1000 > 0) {
|
||||
sinfo.jitter_ms = block.interarrival_jitter / (codec.plfreq / 1000);
|
||||
}
|
||||
sinfo.packets_lost = block.cumulative_num_packets_lost;
|
||||
sinfo.ext_seqnum = block.extended_highest_sequence_number;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Local speech level.
|
||||
unsigned int level = 0;
|
||||
sinfo.audio_level = (engine()->voe()->volume()->
|
||||
GetSpeechInputLevelFullRange(level) != -1) ? level : -1;
|
||||
|
||||
// TODO(xians): We are injecting the same APM logging to all the send
|
||||
// channels here because there is no good way to know which send channel
|
||||
// is using the APM. The correct fix is to allow the send channels to have
|
||||
// their own APM so that we can feed the correct APM logging to different
|
||||
// send channels. See issue crbug/264611 .
|
||||
sinfo.echo_return_loss = echo_return_loss;
|
||||
sinfo.echo_return_loss_enhancement = echo_return_loss_enhancement;
|
||||
sinfo.echo_delay_median_ms = echo_delay_median_ms;
|
||||
sinfo.echo_delay_std_ms = echo_delay_std_ms;
|
||||
// TODO(ajm): Re-enable this metric once we have a reliable implementation.
|
||||
sinfo.aec_quality_min = -1;
|
||||
sinfo.add_ssrc(stats.local_ssrc);
|
||||
sinfo.bytes_sent = stats.bytes_sent;
|
||||
sinfo.packets_sent = stats.packets_sent;
|
||||
sinfo.packets_lost = stats.packets_lost;
|
||||
sinfo.fraction_lost = stats.fraction_lost;
|
||||
sinfo.codec_name = stats.codec_name;
|
||||
sinfo.ext_seqnum = stats.ext_seqnum;
|
||||
sinfo.jitter_ms = stats.jitter_ms;
|
||||
sinfo.rtt_ms = stats.rtt_ms;
|
||||
sinfo.audio_level = stats.audio_level;
|
||||
sinfo.aec_quality_min = stats.aec_quality_min;
|
||||
sinfo.echo_delay_median_ms = stats.echo_delay_median_ms;
|
||||
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;
|
||||
info->senders.push_back(sinfo);
|
||||
}
|
||||
|
||||
// Get the SSRC and stats for each receiver.
|
||||
info->receivers.clear();
|
||||
// Get SSRC and stats for each receiver.
|
||||
RTC_DCHECK(info->receivers.size() == 0);
|
||||
for (const auto& stream : receive_streams_) {
|
||||
webrtc::AudioReceiveStream::Stats stats = stream.second->GetStats();
|
||||
VoiceReceiverInfo rinfo;
|
||||
|
||||
@ -57,9 +57,9 @@ const cricket::AudioCodec* const kAudioCodecs[] = {
|
||||
&kPcmuCodec, &kIsacCodec, &kOpusCodec, &kG722CodecVoE, &kRedCodec,
|
||||
&kCn8000Codec, &kCn16000Codec, &kTelephoneEventCodec,
|
||||
};
|
||||
static uint32_t kSsrc1 = 0x99;
|
||||
static uint32_t kSsrc2 = 0x98;
|
||||
static const uint32_t kSsrcs4[] = {1, 2, 3, 4};
|
||||
const uint32_t kSsrc1 = 0x99;
|
||||
const uint32_t kSsrc2 = 0x98;
|
||||
const uint32_t kSsrcs4[] = { 1, 2, 3, 4 };
|
||||
|
||||
class FakeVoEWrapper : public cricket::VoEWrapper {
|
||||
public:
|
||||
@ -124,13 +124,11 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
|
||||
EXPECT_TRUE(SetupEngineWithSendStream());
|
||||
// Remove stream added in Setup.
|
||||
int default_channel_num = voe_.GetLastChannel();
|
||||
uint32_t default_send_ssrc = 0u;
|
||||
EXPECT_EQ(0, voe_.GetLocalSSRC(default_channel_num, default_send_ssrc));
|
||||
EXPECT_EQ(kSsrc1, default_send_ssrc);
|
||||
EXPECT_TRUE(channel_->RemoveSendStream(default_send_ssrc));
|
||||
EXPECT_EQ(kSsrc1, voe_.GetLocalSSRC(default_channel_num));
|
||||
EXPECT_TRUE(channel_->RemoveSendStream(kSsrc1));
|
||||
|
||||
// Verify the channel does not exist.
|
||||
EXPECT_EQ(-1, voe_.GetLocalSSRC(default_channel_num, default_send_ssrc));
|
||||
EXPECT_EQ(-1, voe_.GetChannelFromLocalSsrc(kSsrc1));
|
||||
}
|
||||
void DeliverPacket(const void* data, int len) {
|
||||
rtc::Buffer packet(reinterpret_cast<const uint8_t*>(data), len);
|
||||
@ -290,34 +288,79 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
|
||||
EXPECT_EQ(-1, voe_.GetReceiveRtpExtensionId(new_channel_num, ext));
|
||||
}
|
||||
|
||||
const webrtc::AudioReceiveStream::Stats& GetAudioReceiveStreamStats() const {
|
||||
static webrtc::AudioReceiveStream::Stats stats;
|
||||
if (stats.remote_ssrc == 0) {
|
||||
stats.remote_ssrc = 123;
|
||||
stats.bytes_rcvd = 456;
|
||||
stats.packets_rcvd = 768;
|
||||
stats.packets_lost = 101;
|
||||
stats.fraction_lost = 23.45f;
|
||||
stats.codec_name = "codec_name";
|
||||
stats.ext_seqnum = 678;
|
||||
stats.jitter_ms = 901;
|
||||
stats.jitter_buffer_ms = 234;
|
||||
stats.jitter_buffer_preferred_ms = 567;
|
||||
stats.delay_estimate_ms = 890;
|
||||
stats.audio_level = 1234;
|
||||
stats.expand_rate = 5.67f;
|
||||
stats.speech_expand_rate = 8.90f;
|
||||
stats.secondary_decoded_rate = 1.23f;
|
||||
stats.accelerate_rate = 4.56f;
|
||||
stats.preemptive_expand_rate = 7.89f;
|
||||
stats.decoding_calls_to_silence_generator = 012;
|
||||
stats.decoding_calls_to_neteq = 345;
|
||||
stats.decoding_normal = 67890;
|
||||
stats.decoding_plc = 1234;
|
||||
stats.decoding_cng = 5678;
|
||||
stats.decoding_plc_cng = 9012;
|
||||
stats.capture_start_ntp_time_ms = 3456;
|
||||
webrtc::AudioSendStream::Stats GetAudioSendStreamStats() const {
|
||||
webrtc::AudioSendStream::Stats stats;
|
||||
stats.local_ssrc = 12;
|
||||
stats.bytes_sent = 345;
|
||||
stats.packets_sent = 678;
|
||||
stats.packets_lost = 9012;
|
||||
stats.fraction_lost = 34.56f;
|
||||
stats.codec_name = "codec_name_send";
|
||||
stats.ext_seqnum = 789;
|
||||
stats.jitter_ms = 12;
|
||||
stats.rtt_ms = 345;
|
||||
stats.audio_level = 678;
|
||||
stats.aec_quality_min = 9.01f;
|
||||
stats.echo_delay_median_ms = 234;
|
||||
stats.echo_delay_std_ms = 567;
|
||||
stats.echo_return_loss = 890;
|
||||
stats.echo_return_loss_enhancement = 1234;
|
||||
stats.typing_noise_detected = true;
|
||||
return stats;
|
||||
}
|
||||
void SetAudioSendStreamStats() {
|
||||
for (auto* s : call_.GetAudioSendStreams()) {
|
||||
s->SetStats(GetAudioSendStreamStats());
|
||||
}
|
||||
}
|
||||
void VerifyVoiceSenderInfo(const cricket::VoiceSenderInfo& info) {
|
||||
const auto stats = GetAudioSendStreamStats();
|
||||
EXPECT_EQ(info.ssrc(), stats.local_ssrc);
|
||||
EXPECT_EQ(info.bytes_sent, stats.bytes_sent);
|
||||
EXPECT_EQ(info.packets_sent, stats.packets_sent);
|
||||
EXPECT_EQ(info.packets_lost, stats.packets_lost);
|
||||
EXPECT_EQ(info.fraction_lost, stats.fraction_lost);
|
||||
EXPECT_EQ(info.codec_name, stats.codec_name);
|
||||
EXPECT_EQ(info.ext_seqnum, stats.ext_seqnum);
|
||||
EXPECT_EQ(info.jitter_ms, stats.jitter_ms);
|
||||
EXPECT_EQ(info.rtt_ms, stats.rtt_ms);
|
||||
EXPECT_EQ(info.audio_level, stats.audio_level);
|
||||
EXPECT_EQ(info.aec_quality_min, stats.aec_quality_min);
|
||||
EXPECT_EQ(info.echo_delay_median_ms, stats.echo_delay_median_ms);
|
||||
EXPECT_EQ(info.echo_delay_std_ms, stats.echo_delay_std_ms);
|
||||
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);
|
||||
}
|
||||
|
||||
webrtc::AudioReceiveStream::Stats GetAudioReceiveStreamStats() const {
|
||||
webrtc::AudioReceiveStream::Stats stats;
|
||||
stats.remote_ssrc = 123;
|
||||
stats.bytes_rcvd = 456;
|
||||
stats.packets_rcvd = 768;
|
||||
stats.packets_lost = 101;
|
||||
stats.fraction_lost = 23.45f;
|
||||
stats.codec_name = "codec_name_recv";
|
||||
stats.ext_seqnum = 678;
|
||||
stats.jitter_ms = 901;
|
||||
stats.jitter_buffer_ms = 234;
|
||||
stats.jitter_buffer_preferred_ms = 567;
|
||||
stats.delay_estimate_ms = 890;
|
||||
stats.audio_level = 1234;
|
||||
stats.expand_rate = 5.67f;
|
||||
stats.speech_expand_rate = 8.90f;
|
||||
stats.secondary_decoded_rate = 1.23f;
|
||||
stats.accelerate_rate = 4.56f;
|
||||
stats.preemptive_expand_rate = 7.89f;
|
||||
stats.decoding_calls_to_silence_generator = 12;
|
||||
stats.decoding_calls_to_neteq = 345;
|
||||
stats.decoding_normal = 67890;
|
||||
stats.decoding_plc = 1234;
|
||||
stats.decoding_cng = 5678;
|
||||
stats.decoding_plc_cng = 9012;
|
||||
stats.capture_start_ntp_time_ms = 3456;
|
||||
return stats;
|
||||
}
|
||||
void SetAudioReceiveStreamStats() {
|
||||
@ -326,33 +369,33 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
|
||||
}
|
||||
}
|
||||
void VerifyVoiceReceiverInfo(const cricket::VoiceReceiverInfo& info) {
|
||||
const auto& kStats = GetAudioReceiveStreamStats();
|
||||
EXPECT_EQ(info.local_stats.front().ssrc, kStats.remote_ssrc);
|
||||
EXPECT_EQ(info.bytes_rcvd, kStats.bytes_rcvd);
|
||||
EXPECT_EQ(info.packets_rcvd, kStats.packets_rcvd);
|
||||
EXPECT_EQ(info.packets_lost, kStats.packets_lost);
|
||||
EXPECT_EQ(info.fraction_lost, kStats.fraction_lost);
|
||||
EXPECT_EQ(info.codec_name, kStats.codec_name);
|
||||
EXPECT_EQ(info.ext_seqnum, kStats.ext_seqnum);
|
||||
EXPECT_EQ(info.jitter_ms, kStats.jitter_ms);
|
||||
EXPECT_EQ(info.jitter_buffer_ms, kStats.jitter_buffer_ms);
|
||||
const auto stats = GetAudioReceiveStreamStats();
|
||||
EXPECT_EQ(info.ssrc(), stats.remote_ssrc);
|
||||
EXPECT_EQ(info.bytes_rcvd, stats.bytes_rcvd);
|
||||
EXPECT_EQ(info.packets_rcvd, stats.packets_rcvd);
|
||||
EXPECT_EQ(info.packets_lost, stats.packets_lost);
|
||||
EXPECT_EQ(info.fraction_lost, stats.fraction_lost);
|
||||
EXPECT_EQ(info.codec_name, stats.codec_name);
|
||||
EXPECT_EQ(info.ext_seqnum, stats.ext_seqnum);
|
||||
EXPECT_EQ(info.jitter_ms, stats.jitter_ms);
|
||||
EXPECT_EQ(info.jitter_buffer_ms, stats.jitter_buffer_ms);
|
||||
EXPECT_EQ(info.jitter_buffer_preferred_ms,
|
||||
kStats.jitter_buffer_preferred_ms);
|
||||
EXPECT_EQ(info.delay_estimate_ms, kStats.delay_estimate_ms);
|
||||
EXPECT_EQ(info.audio_level, kStats.audio_level);
|
||||
EXPECT_EQ(info.expand_rate, kStats.expand_rate);
|
||||
EXPECT_EQ(info.speech_expand_rate, kStats.speech_expand_rate);
|
||||
EXPECT_EQ(info.secondary_decoded_rate, kStats.secondary_decoded_rate);
|
||||
EXPECT_EQ(info.accelerate_rate, kStats.accelerate_rate);
|
||||
EXPECT_EQ(info.preemptive_expand_rate, kStats.preemptive_expand_rate);
|
||||
stats.jitter_buffer_preferred_ms);
|
||||
EXPECT_EQ(info.delay_estimate_ms, stats.delay_estimate_ms);
|
||||
EXPECT_EQ(info.audio_level, stats.audio_level);
|
||||
EXPECT_EQ(info.expand_rate, stats.expand_rate);
|
||||
EXPECT_EQ(info.speech_expand_rate, stats.speech_expand_rate);
|
||||
EXPECT_EQ(info.secondary_decoded_rate, stats.secondary_decoded_rate);
|
||||
EXPECT_EQ(info.accelerate_rate, stats.accelerate_rate);
|
||||
EXPECT_EQ(info.preemptive_expand_rate, stats.preemptive_expand_rate);
|
||||
EXPECT_EQ(info.decoding_calls_to_silence_generator,
|
||||
kStats.decoding_calls_to_silence_generator);
|
||||
EXPECT_EQ(info.decoding_calls_to_neteq, kStats.decoding_calls_to_neteq);
|
||||
EXPECT_EQ(info.decoding_normal, kStats.decoding_normal);
|
||||
EXPECT_EQ(info.decoding_plc, kStats.decoding_plc);
|
||||
EXPECT_EQ(info.decoding_cng, kStats.decoding_cng);
|
||||
EXPECT_EQ(info.decoding_plc_cng, kStats.decoding_plc_cng);
|
||||
EXPECT_EQ(info.capture_start_ntp_time_ms, kStats.capture_start_ntp_time_ms);
|
||||
stats.decoding_calls_to_silence_generator);
|
||||
EXPECT_EQ(info.decoding_calls_to_neteq, stats.decoding_calls_to_neteq);
|
||||
EXPECT_EQ(info.decoding_normal, stats.decoding_normal);
|
||||
EXPECT_EQ(info.decoding_plc, stats.decoding_plc);
|
||||
EXPECT_EQ(info.decoding_cng, stats.decoding_cng);
|
||||
EXPECT_EQ(info.decoding_plc_cng, stats.decoding_plc_cng);
|
||||
EXPECT_EQ(info.capture_start_ntp_time_ms, stats.capture_start_ntp_time_ms);
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -2028,6 +2071,8 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStatsWithMultipleSendStreams) {
|
||||
EXPECT_TRUE(channel_->AddSendStream(
|
||||
cricket::StreamParams::CreateLegacy(ssrc)));
|
||||
}
|
||||
SetAudioSendStreamStats();
|
||||
|
||||
// Create a receive stream to check that none of the send streams end up in
|
||||
// the receive stream stats.
|
||||
EXPECT_TRUE(channel_->AddRecvStream(
|
||||
@ -2036,41 +2081,42 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStatsWithMultipleSendStreams) {
|
||||
EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
|
||||
EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
|
||||
|
||||
cricket::VoiceMediaInfo info;
|
||||
EXPECT_EQ(true, channel_->GetStats(&info));
|
||||
EXPECT_EQ(static_cast<size_t>(ARRAY_SIZE(kSsrcs4)), info.senders.size());
|
||||
// Check stats for the added streams.
|
||||
{
|
||||
cricket::VoiceMediaInfo info;
|
||||
EXPECT_EQ(true, channel_->GetStats(&info));
|
||||
|
||||
// Verify the statistic information is correct.
|
||||
// TODO(solenberg): Make this loop ordering independent.
|
||||
for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) {
|
||||
EXPECT_EQ(kSsrcs4[i], info.senders[i].ssrc());
|
||||
EXPECT_EQ(kPcmuCodec.name, info.senders[i].codec_name);
|
||||
EXPECT_EQ(cricket::kIntStatValue, info.senders[i].bytes_sent);
|
||||
EXPECT_EQ(cricket::kIntStatValue, info.senders[i].packets_sent);
|
||||
EXPECT_EQ(cricket::kIntStatValue, info.senders[i].packets_lost);
|
||||
EXPECT_EQ(cricket::kFractionLostStatValue, info.senders[i].fraction_lost);
|
||||
EXPECT_EQ(cricket::kIntStatValue, info.senders[i].ext_seqnum);
|
||||
EXPECT_EQ(cricket::kIntStatValue, info.senders[i].rtt_ms);
|
||||
EXPECT_EQ(cricket::kIntStatValue, info.senders[i].jitter_ms);
|
||||
EXPECT_EQ(kPcmuCodec.name, info.senders[i].codec_name);
|
||||
// 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());
|
||||
for (const auto& sender : info.senders) {
|
||||
VerifyVoiceSenderInfo(sender);
|
||||
}
|
||||
|
||||
// We have added one receive stream. We should see empty stats.
|
||||
EXPECT_EQ(info.receivers.size(), 1u);
|
||||
EXPECT_EQ(info.receivers[0].ssrc(), 0);
|
||||
}
|
||||
|
||||
// We have added one receive stream. We should see empty stats.
|
||||
EXPECT_EQ(info.receivers.size(), 1u);
|
||||
EXPECT_EQ(info.receivers[0].local_stats.front().ssrc, 0);
|
||||
|
||||
// Remove the kSsrc2 stream. No receiver stats.
|
||||
EXPECT_TRUE(channel_->RemoveRecvStream(kSsrc2));
|
||||
EXPECT_EQ(true, channel_->GetStats(&info));
|
||||
EXPECT_EQ(0u, info.receivers.size());
|
||||
{
|
||||
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(0u, info.receivers.size());
|
||||
}
|
||||
|
||||
// Deliver a new packet - a default receive stream should be created and we
|
||||
// should see stats again.
|
||||
DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame));
|
||||
SetAudioReceiveStreamStats();
|
||||
EXPECT_EQ(true, channel_->GetStats(&info));
|
||||
EXPECT_EQ(1u, info.receivers.size());
|
||||
VerifyVoiceReceiverInfo(info.receivers[0]);
|
||||
{
|
||||
cricket::VoiceMediaInfo info;
|
||||
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(1u, info.receivers.size());
|
||||
VerifyVoiceReceiverInfo(info.receivers[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Test that we can add and remove receive streams, and do proper send/playout.
|
||||
@ -2292,17 +2338,13 @@ TEST_F(WebRtcVoiceEngineTestFake, TraceFilterViaTraceOptions) {
|
||||
// SSRC is set in SetupEngine by calling AddSendStream.
|
||||
TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrc) {
|
||||
EXPECT_TRUE(SetupEngineWithSendStream());
|
||||
int channel_num = voe_.GetLastChannel();
|
||||
unsigned int send_ssrc;
|
||||
EXPECT_EQ(0, voe_.GetLocalSSRC(channel_num, send_ssrc));
|
||||
EXPECT_NE(0U, send_ssrc);
|
||||
EXPECT_EQ(0, voe_.GetLocalSSRC(channel_num, send_ssrc));
|
||||
EXPECT_EQ(kSsrc1, send_ssrc);
|
||||
EXPECT_EQ(kSsrc1, voe_.GetLocalSSRC(voe_.GetLastChannel()));
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVoiceEngineTestFake, GetStats) {
|
||||
// Setup. We need send codec to be set to get all stats.
|
||||
EXPECT_TRUE(SetupEngineWithSendStream());
|
||||
SetAudioSendStreamStats();
|
||||
// SetupEngineWithSendStream adds a send stream with kSsrc1, so the receive
|
||||
// stream has to use a different SSRC.
|
||||
EXPECT_TRUE(channel_->AddRecvStream(
|
||||
@ -2310,58 +2352,48 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStats) {
|
||||
EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
|
||||
EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
|
||||
|
||||
cricket::VoiceMediaInfo info;
|
||||
EXPECT_EQ(true, channel_->GetStats(&info));
|
||||
EXPECT_EQ(1u, info.senders.size());
|
||||
EXPECT_EQ(kSsrc1, info.senders[0].ssrc());
|
||||
EXPECT_EQ(kPcmuCodec.name, info.senders[0].codec_name);
|
||||
EXPECT_EQ(cricket::kIntStatValue, info.senders[0].bytes_sent);
|
||||
EXPECT_EQ(cricket::kIntStatValue, info.senders[0].packets_sent);
|
||||
EXPECT_EQ(cricket::kIntStatValue, info.senders[0].packets_lost);
|
||||
EXPECT_EQ(cricket::kFractionLostStatValue, info.senders[0].fraction_lost);
|
||||
EXPECT_EQ(cricket::kIntStatValue, info.senders[0].ext_seqnum);
|
||||
EXPECT_EQ(cricket::kIntStatValue, info.senders[0].rtt_ms);
|
||||
EXPECT_EQ(cricket::kIntStatValue, info.senders[0].jitter_ms);
|
||||
EXPECT_EQ(kPcmuCodec.name, info.senders[0].codec_name);
|
||||
// TODO(sriniv): Add testing for more fields. These are not populated
|
||||
// in FakeWebrtcVoiceEngine yet.
|
||||
// EXPECT_EQ(cricket::kIntStatValue, info.senders[0].audio_level);
|
||||
// EXPECT_EQ(cricket::kIntStatValue, info.senders[0].echo_delay_median_ms);
|
||||
// EXPECT_EQ(cricket::kIntStatValue, info.senders[0].echo_delay_std_ms);
|
||||
// EXPECT_EQ(cricket::kIntStatValue, info.senders[0].echo_return_loss);
|
||||
// EXPECT_EQ(cricket::kIntStatValue,
|
||||
// info.senders[0].echo_return_loss_enhancement);
|
||||
// We have added one receive stream. We should see empty stats.
|
||||
EXPECT_EQ(info.receivers.size(), 1u);
|
||||
EXPECT_EQ(info.receivers[0].local_stats.front().ssrc, 0);
|
||||
// Check stats for the added streams.
|
||||
{
|
||||
cricket::VoiceMediaInfo info;
|
||||
EXPECT_EQ(true, channel_->GetStats(&info));
|
||||
|
||||
// We have added one send stream. We should see the stats we've set.
|
||||
EXPECT_EQ(1u, info.senders.size());
|
||||
VerifyVoiceSenderInfo(info.senders[0]);
|
||||
// We have added one receive stream. We should see empty stats.
|
||||
EXPECT_EQ(info.receivers.size(), 1u);
|
||||
EXPECT_EQ(info.receivers[0].ssrc(), 0);
|
||||
}
|
||||
|
||||
// Remove the kSsrc2 stream. No receiver stats.
|
||||
EXPECT_TRUE(channel_->RemoveRecvStream(kSsrc2));
|
||||
EXPECT_EQ(true, channel_->GetStats(&info));
|
||||
EXPECT_EQ(0u, info.receivers.size());
|
||||
{
|
||||
cricket::VoiceMediaInfo info;
|
||||
EXPECT_TRUE(channel_->RemoveRecvStream(kSsrc2));
|
||||
EXPECT_EQ(true, channel_->GetStats(&info));
|
||||
EXPECT_EQ(1u, info.senders.size());
|
||||
EXPECT_EQ(0u, info.receivers.size());
|
||||
}
|
||||
|
||||
// Deliver a new packet - a default receive stream should be created and we
|
||||
// should see stats again.
|
||||
DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame));
|
||||
SetAudioReceiveStreamStats();
|
||||
EXPECT_EQ(true, channel_->GetStats(&info));
|
||||
EXPECT_EQ(1u, info.receivers.size());
|
||||
VerifyVoiceReceiverInfo(info.receivers[0]);
|
||||
{
|
||||
cricket::VoiceMediaInfo info;
|
||||
DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame));
|
||||
SetAudioReceiveStreamStats();
|
||||
EXPECT_EQ(true, channel_->GetStats(&info));
|
||||
EXPECT_EQ(1u, info.senders.size());
|
||||
EXPECT_EQ(1u, info.receivers.size());
|
||||
VerifyVoiceReceiverInfo(info.receivers[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Test that we can set the outgoing SSRC properly with multiple streams.
|
||||
// SSRC is set in SetupEngine by calling AddSendStream.
|
||||
TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrcWithMultipleStreams) {
|
||||
EXPECT_TRUE(SetupEngineWithSendStream());
|
||||
int channel_num1 = voe_.GetLastChannel();
|
||||
unsigned int send_ssrc;
|
||||
EXPECT_EQ(0, voe_.GetLocalSSRC(channel_num1, send_ssrc));
|
||||
EXPECT_EQ(kSsrc1, send_ssrc);
|
||||
|
||||
EXPECT_EQ(kSsrc1, voe_.GetLocalSSRC(voe_.GetLastChannel()));
|
||||
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
|
||||
int channel_num2 = voe_.GetLastChannel();
|
||||
EXPECT_EQ(0, voe_.GetLocalSSRC(channel_num2, send_ssrc));
|
||||
EXPECT_EQ(kSsrc1, send_ssrc);
|
||||
EXPECT_EQ(kSsrc1, voe_.GetLocalSSRC(voe_.GetLastChannel()));
|
||||
}
|
||||
|
||||
// Test that the local SSRC is the same on sending and receiving channels if the
|
||||
@ -2376,12 +2408,8 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrcAfterCreatingReceiveChannel) {
|
||||
cricket::StreamParams::CreateLegacy(1234)));
|
||||
int send_channel_num = voe_.GetLastChannel();
|
||||
|
||||
unsigned int ssrc = 0;
|
||||
EXPECT_EQ(0, voe_.GetLocalSSRC(send_channel_num, ssrc));
|
||||
EXPECT_EQ(1234U, ssrc);
|
||||
ssrc = 0;
|
||||
EXPECT_EQ(0, voe_.GetLocalSSRC(receive_channel_num, ssrc));
|
||||
EXPECT_EQ(1234U, ssrc);
|
||||
EXPECT_EQ(1234U, voe_.GetLocalSSRC(send_channel_num));
|
||||
EXPECT_EQ(1234U, voe_.GetLocalSSRC(receive_channel_num));
|
||||
}
|
||||
|
||||
// Test that we can properly receive packets.
|
||||
@ -2545,7 +2573,6 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
|
||||
|
||||
bool ec_enabled;
|
||||
webrtc::EcModes ec_mode;
|
||||
bool ec_metrics_enabled;
|
||||
webrtc::AecmModes aecm_mode;
|
||||
bool cng_enabled;
|
||||
bool agc_enabled;
|
||||
@ -2557,7 +2584,6 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
|
||||
bool stereo_swapping_enabled;
|
||||
bool typing_detection_enabled;
|
||||
voe_.GetEcStatus(ec_enabled, ec_mode);
|
||||
voe_.GetEcMetricsStatus(ec_metrics_enabled);
|
||||
voe_.GetAecmMode(aecm_mode, cng_enabled);
|
||||
voe_.GetAgcStatus(agc_enabled, agc_mode);
|
||||
voe_.GetAgcConfig(agc_config);
|
||||
@ -2566,7 +2592,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
|
||||
stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
|
||||
voe_.GetTypingDetectionStatus(typing_detection_enabled);
|
||||
EXPECT_TRUE(ec_enabled);
|
||||
EXPECT_TRUE(ec_metrics_enabled);
|
||||
EXPECT_TRUE(voe_.ec_metrics_enabled());
|
||||
EXPECT_FALSE(cng_enabled);
|
||||
EXPECT_TRUE(agc_enabled);
|
||||
EXPECT_EQ(0, agc_config.targetLeveldBOv);
|
||||
@ -2581,7 +2607,6 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
|
||||
cricket::AudioOptions options;
|
||||
ASSERT_TRUE(engine_.SetOptions(options));
|
||||
voe_.GetEcStatus(ec_enabled, ec_mode);
|
||||
voe_.GetEcMetricsStatus(ec_metrics_enabled);
|
||||
voe_.GetAecmMode(aecm_mode, cng_enabled);
|
||||
voe_.GetAgcStatus(agc_enabled, agc_mode);
|
||||
voe_.GetAgcConfig(agc_config);
|
||||
@ -2590,7 +2615,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
|
||||
stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
|
||||
voe_.GetTypingDetectionStatus(typing_detection_enabled);
|
||||
EXPECT_TRUE(ec_enabled);
|
||||
EXPECT_TRUE(ec_metrics_enabled);
|
||||
EXPECT_TRUE(voe_.ec_metrics_enabled());
|
||||
EXPECT_FALSE(cng_enabled);
|
||||
EXPECT_TRUE(agc_enabled);
|
||||
EXPECT_EQ(0, agc_config.targetLeveldBOv);
|
||||
@ -2615,7 +2640,6 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
|
||||
options.echo_cancellation.Set(true);
|
||||
ASSERT_TRUE(engine_.SetOptions(options));
|
||||
voe_.GetEcStatus(ec_enabled, ec_mode);
|
||||
voe_.GetEcMetricsStatus(ec_metrics_enabled);
|
||||
voe_.GetAecmMode(aecm_mode, cng_enabled);
|
||||
voe_.GetAgcStatus(agc_enabled, agc_mode);
|
||||
voe_.GetAgcConfig(agc_config);
|
||||
@ -2624,7 +2648,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
|
||||
stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
|
||||
voe_.GetTypingDetectionStatus(typing_detection_enabled);
|
||||
EXPECT_TRUE(ec_enabled);
|
||||
EXPECT_TRUE(ec_metrics_enabled);
|
||||
EXPECT_TRUE(voe_.ec_metrics_enabled());
|
||||
EXPECT_TRUE(agc_enabled);
|
||||
EXPECT_EQ(0, agc_config.targetLeveldBOv);
|
||||
EXPECT_TRUE(ns_enabled);
|
||||
@ -2639,10 +2663,9 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
|
||||
options.delay_agnostic_aec.Set(true);
|
||||
ASSERT_TRUE(engine_.SetOptions(options));
|
||||
voe_.GetEcStatus(ec_enabled, ec_mode);
|
||||
voe_.GetEcMetricsStatus(ec_metrics_enabled);
|
||||
voe_.GetAecmMode(aecm_mode, cng_enabled);
|
||||
EXPECT_TRUE(ec_enabled);
|
||||
EXPECT_TRUE(ec_metrics_enabled);
|
||||
EXPECT_TRUE(voe_.ec_metrics_enabled());
|
||||
EXPECT_EQ(ec_mode, webrtc::kEcConference);
|
||||
|
||||
// Turn off echo cancellation and delay agnostic aec.
|
||||
@ -2656,9 +2679,8 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
|
||||
options.delay_agnostic_aec.Set(true);
|
||||
ASSERT_TRUE(engine_.SetOptions(options));
|
||||
voe_.GetEcStatus(ec_enabled, ec_mode);
|
||||
voe_.GetEcMetricsStatus(ec_metrics_enabled);
|
||||
EXPECT_TRUE(ec_enabled);
|
||||
EXPECT_TRUE(ec_metrics_enabled);
|
||||
EXPECT_TRUE(voe_.ec_metrics_enabled());
|
||||
EXPECT_EQ(ec_mode, webrtc::kEcConference);
|
||||
|
||||
// Turn off AGC
|
||||
@ -2706,7 +2728,6 @@ TEST_F(WebRtcVoiceEngineTestFake, DefaultOptions) {
|
||||
|
||||
bool ec_enabled;
|
||||
webrtc::EcModes ec_mode;
|
||||
bool ec_metrics_enabled;
|
||||
bool agc_enabled;
|
||||
webrtc::AgcModes agc_mode;
|
||||
bool ns_enabled;
|
||||
@ -2716,7 +2737,6 @@ TEST_F(WebRtcVoiceEngineTestFake, DefaultOptions) {
|
||||
bool typing_detection_enabled;
|
||||
|
||||
voe_.GetEcStatus(ec_enabled, ec_mode);
|
||||
voe_.GetEcMetricsStatus(ec_metrics_enabled);
|
||||
voe_.GetAgcStatus(agc_enabled, agc_mode);
|
||||
voe_.GetNsStatus(ns_enabled, ns_mode);
|
||||
highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
|
||||
@ -2978,7 +2998,7 @@ TEST_F(WebRtcVoiceEngineTestFake, CanChangeCombinedBweOption) {
|
||||
for (uint32_t ssrc : ssrcs) {
|
||||
const auto* s = call_.GetAudioReceiveStream(ssrc);
|
||||
EXPECT_NE(nullptr, s);
|
||||
EXPECT_EQ(false, s->GetConfig().combined_audio_video_bwe);
|
||||
EXPECT_FALSE(s->GetConfig().combined_audio_video_bwe);
|
||||
}
|
||||
|
||||
// Enable combined BWE option - now it should be set up.
|
||||
@ -2996,7 +3016,7 @@ TEST_F(WebRtcVoiceEngineTestFake, CanChangeCombinedBweOption) {
|
||||
for (uint32_t ssrc : ssrcs) {
|
||||
const auto* s = call_.GetAudioReceiveStream(ssrc);
|
||||
EXPECT_NE(nullptr, s);
|
||||
EXPECT_EQ(false, s->GetConfig().combined_audio_video_bwe);
|
||||
EXPECT_FALSE(s->GetConfig().combined_audio_video_bwe);
|
||||
}
|
||||
|
||||
EXPECT_EQ(2, call_.GetAudioReceiveStreams().size());
|
||||
|
||||
@ -28,6 +28,7 @@ namespace webrtc {
|
||||
std::string AudioReceiveStream::Config::Rtp::ToString() const {
|
||||
std::stringstream ss;
|
||||
ss << "{remote_ssrc: " << remote_ssrc;
|
||||
ss << ", local_ssrc: " << local_ssrc;
|
||||
ss << ", extensions: [";
|
||||
for (size_t i = 0; i < extensions.size(); ++i) {
|
||||
ss << extensions[i].ToString();
|
||||
@ -43,10 +44,16 @@ std::string AudioReceiveStream::Config::Rtp::ToString() const {
|
||||
std::string AudioReceiveStream::Config::ToString() const {
|
||||
std::stringstream ss;
|
||||
ss << "{rtp: " << rtp.ToString();
|
||||
ss << ", receive_transport: "
|
||||
<< (receive_transport ? "(Transport)" : "nullptr");
|
||||
ss << ", rtcp_send_transport: "
|
||||
<< (rtcp_send_transport ? "(Transport)" : "nullptr");
|
||||
ss << ", voe_channel_id: " << voe_channel_id;
|
||||
if (!sync_group.empty()) {
|
||||
ss << ", sync_group: " << sync_group;
|
||||
}
|
||||
ss << ", combined_audio_video_bwe: "
|
||||
<< (combined_audio_video_bwe ? "true" : "false");
|
||||
ss << '}';
|
||||
return ss.str();
|
||||
}
|
||||
@ -61,7 +68,6 @@ AudioReceiveStream::AudioReceiveStream(
|
||||
voice_engine_(voice_engine),
|
||||
voe_base_(voice_engine),
|
||||
rtp_header_parser_(RtpHeaderParser::Create()) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
LOG(LS_INFO) << "AudioReceiveStream: " << config_.ToString();
|
||||
RTC_DCHECK(config.voe_channel_id != -1);
|
||||
RTC_DCHECK(remote_bitrate_estimator_ != nullptr);
|
||||
@ -101,26 +107,25 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
|
||||
ScopedVoEInterface<VoEVideoSync> sync(voice_engine_);
|
||||
ScopedVoEInterface<VoEVolumeControl> volume(voice_engine_);
|
||||
unsigned int ssrc = 0;
|
||||
webrtc::CallStatistics cs = {0};
|
||||
webrtc::CodecInst ci = {0};
|
||||
webrtc::CallStatistics call_stats = {0};
|
||||
webrtc::CodecInst codec_inst = {0};
|
||||
// Only collect stats if we have seen some traffic with the SSRC.
|
||||
if (rtp->GetRemoteSSRC(config_.voe_channel_id, ssrc) == -1 ||
|
||||
rtp->GetRTCPStatistics(config_.voe_channel_id, cs) == -1 ||
|
||||
codec->GetRecCodec(config_.voe_channel_id, ci) == -1) {
|
||||
rtp->GetRTCPStatistics(config_.voe_channel_id, call_stats) == -1 ||
|
||||
codec->GetRecCodec(config_.voe_channel_id, codec_inst) == -1) {
|
||||
return stats;
|
||||
}
|
||||
|
||||
stats.bytes_rcvd = cs.bytesReceived;
|
||||
stats.packets_rcvd = cs.packetsReceived;
|
||||
stats.packets_lost = cs.cumulativeLost;
|
||||
stats.fraction_lost = static_cast<float>(cs.fractionLost) / (1 << 8);
|
||||
if (ci.pltype != -1) {
|
||||
stats.codec_name = ci.plname;
|
||||
stats.bytes_rcvd = call_stats.bytesReceived;
|
||||
stats.packets_rcvd = call_stats.packetsReceived;
|
||||
stats.packets_lost = call_stats.cumulativeLost;
|
||||
stats.fraction_lost = Q8ToFloat(call_stats.fractionLost);
|
||||
if (codec_inst.pltype != -1) {
|
||||
stats.codec_name = codec_inst.plname;
|
||||
}
|
||||
|
||||
stats.ext_seqnum = cs.extendedMax;
|
||||
if (ci.plfreq / 1000 > 0) {
|
||||
stats.jitter_ms = cs.jitterSamples / (ci.plfreq / 1000);
|
||||
stats.ext_seqnum = call_stats.extendedMax;
|
||||
if (codec_inst.plfreq / 1000 > 0) {
|
||||
stats.jitter_ms = call_stats.jitterSamples / (codec_inst.plfreq / 1000);
|
||||
}
|
||||
{
|
||||
int jitter_buffer_delay_ms = 0;
|
||||
@ -161,7 +166,7 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
|
||||
stats.decoding_plc_cng = ds.decoded_plc_cng;
|
||||
}
|
||||
|
||||
stats.capture_start_ntp_time_ms = cs.capture_start_ntp_time_ms_;
|
||||
stats.capture_start_ntp_time_ms = call_stats.capture_start_ntp_time_ms_;
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ class VoiceEngine;
|
||||
|
||||
namespace internal {
|
||||
|
||||
class AudioReceiveStream : public webrtc::AudioReceiveStream {
|
||||
class AudioReceiveStream final : public webrtc::AudioReceiveStream {
|
||||
public:
|
||||
AudioReceiveStream(RemoteBitrateEstimator* remote_bitrate_estimator,
|
||||
const webrtc::AudioReceiveStream::Config& config,
|
||||
@ -53,6 +53,8 @@ class AudioReceiveStream : public webrtc::AudioReceiveStream {
|
||||
// We hold one interface pointer to the VoE to make sure it is kept alive.
|
||||
ScopedVoEInterface<VoEBase> voe_base_;
|
||||
rtc::scoped_ptr<RtpHeaderParser> rtp_header_parser_;
|
||||
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioReceiveStream);
|
||||
};
|
||||
} // namespace internal
|
||||
} // namespace webrtc
|
||||
|
||||
@ -61,12 +61,36 @@ size_t CreateRtpHeaderWithAbsSendTime(uint8_t* header,
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
TEST(AudioReceiveStreamTest, ConfigToString) {
|
||||
const int kAbsSendTimeId = 3;
|
||||
AudioReceiveStream::Config config;
|
||||
config.rtp.remote_ssrc = 1234;
|
||||
config.rtp.local_ssrc = 5678;
|
||||
config.rtp.extensions.push_back(
|
||||
RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeId));
|
||||
config.voe_channel_id = 1;
|
||||
config.combined_audio_video_bwe = true;
|
||||
EXPECT_EQ("{rtp: {remote_ssrc: 1234, local_ssrc: 5678, extensions: [{name: "
|
||||
"http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time, id: 3}]}, "
|
||||
"receive_transport: nullptr, rtcp_send_transport: nullptr, "
|
||||
"voe_channel_id: 1, combined_audio_video_bwe: true}", config.ToString());
|
||||
}
|
||||
|
||||
TEST(AudioReceiveStreamTest, ConstructDestruct) {
|
||||
MockRemoteBitrateEstimator remote_bitrate_estimator;
|
||||
FakeVoiceEngine voice_engine;
|
||||
AudioReceiveStream::Config config;
|
||||
config.voe_channel_id = 1;
|
||||
internal::AudioReceiveStream recv_stream(&remote_bitrate_estimator, config,
|
||||
&voice_engine);
|
||||
}
|
||||
|
||||
TEST(AudioReceiveStreamTest, AudioPacketUpdatesBweWithTimestamp) {
|
||||
MockRemoteBitrateEstimator remote_bitrate_estimator;
|
||||
FakeVoiceEngine voice_engine;
|
||||
AudioReceiveStream::Config config;
|
||||
config.combined_audio_video_bwe = true;
|
||||
config.voe_channel_id = voice_engine.kReceiveChannelId;
|
||||
config.voe_channel_id = FakeVoiceEngine::kRecvChannelId;
|
||||
const int kAbsSendTimeId = 3;
|
||||
config.rtp.extensions.push_back(
|
||||
RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeId));
|
||||
@ -86,38 +110,35 @@ TEST(AudioReceiveStreamTest, AudioPacketUpdatesBweWithTimestamp) {
|
||||
}
|
||||
|
||||
TEST(AudioReceiveStreamTest, GetStats) {
|
||||
const uint32_t kSsrc1 = 667;
|
||||
|
||||
MockRemoteBitrateEstimator remote_bitrate_estimator;
|
||||
FakeVoiceEngine voice_engine;
|
||||
AudioReceiveStream::Config config;
|
||||
config.rtp.remote_ssrc = kSsrc1;
|
||||
config.voe_channel_id = voice_engine.kReceiveChannelId;
|
||||
config.rtp.remote_ssrc = FakeVoiceEngine::kRecvSsrc;
|
||||
config.voe_channel_id = FakeVoiceEngine::kRecvChannelId;
|
||||
internal::AudioReceiveStream recv_stream(&remote_bitrate_estimator, config,
|
||||
&voice_engine);
|
||||
|
||||
AudioReceiveStream::Stats stats = recv_stream.GetStats();
|
||||
const CallStatistics& call_stats = voice_engine.GetRecvCallStats();
|
||||
const CodecInst& codec_inst = voice_engine.GetRecvRecCodecInst();
|
||||
const NetworkStatistics& net_stats = voice_engine.GetRecvNetworkStats();
|
||||
const CallStatistics& call_stats = FakeVoiceEngine::kRecvCallStats;
|
||||
const CodecInst& codec_inst = FakeVoiceEngine::kRecvCodecInst;
|
||||
const NetworkStatistics& net_stats = FakeVoiceEngine::kRecvNetworkStats;
|
||||
const AudioDecodingCallStats& decode_stats =
|
||||
voice_engine.GetRecvAudioDecodingCallStats();
|
||||
EXPECT_EQ(kSsrc1, stats.remote_ssrc);
|
||||
FakeVoiceEngine::kRecvAudioDecodingCallStats;
|
||||
EXPECT_EQ(FakeVoiceEngine::kRecvSsrc, stats.remote_ssrc);
|
||||
EXPECT_EQ(static_cast<int64_t>(call_stats.bytesReceived), stats.bytes_rcvd);
|
||||
EXPECT_EQ(static_cast<uint32_t>(call_stats.packetsReceived),
|
||||
stats.packets_rcvd);
|
||||
EXPECT_EQ(call_stats.cumulativeLost, stats.packets_lost);
|
||||
EXPECT_EQ(static_cast<float>(call_stats.fractionLost) / 256,
|
||||
stats.fraction_lost);
|
||||
EXPECT_EQ(Q8ToFloat(call_stats.fractionLost), stats.fraction_lost);
|
||||
EXPECT_EQ(std::string(codec_inst.plname), stats.codec_name);
|
||||
EXPECT_EQ(call_stats.extendedMax, stats.ext_seqnum);
|
||||
EXPECT_EQ(call_stats.jitterSamples / (codec_inst.plfreq / 1000),
|
||||
stats.jitter_ms);
|
||||
EXPECT_EQ(net_stats.currentBufferSize, stats.jitter_buffer_ms);
|
||||
EXPECT_EQ(net_stats.preferredBufferSize, stats.jitter_buffer_preferred_ms);
|
||||
EXPECT_EQ(static_cast<uint32_t>(voice_engine.kRecvJitterBufferDelay +
|
||||
voice_engine.kRecvPlayoutBufferDelay), stats.delay_estimate_ms);
|
||||
EXPECT_EQ(static_cast<int32_t>(voice_engine.kRecvSpeechOutputLevel),
|
||||
EXPECT_EQ(static_cast<uint32_t>(FakeVoiceEngine::kRecvJitterBufferDelay +
|
||||
FakeVoiceEngine::kRecvPlayoutBufferDelay), stats.delay_estimate_ms);
|
||||
EXPECT_EQ(static_cast<int32_t>(FakeVoiceEngine::kRecvSpeechOutputLevel),
|
||||
stats.audio_level);
|
||||
EXPECT_EQ(Q14ToFloat(net_stats.currentExpandRate), stats.expand_rate);
|
||||
EXPECT_EQ(Q14ToFloat(net_stats.currentSpeechExpandRate),
|
||||
|
||||
@ -12,8 +12,13 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "webrtc/audio/conversion.h"
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/voice_engine/include/voe_audio_processing.h"
|
||||
#include "webrtc/voice_engine/include/voe_codec.h"
|
||||
#include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
|
||||
#include "webrtc/voice_engine/include/voe_volume_control.h"
|
||||
|
||||
namespace webrtc {
|
||||
std::string AudioSendStream::Config::Rtp::ToString() const {
|
||||
@ -22,8 +27,9 @@ std::string AudioSendStream::Config::Rtp::ToString() const {
|
||||
ss << ", extensions: [";
|
||||
for (size_t i = 0; i < extensions.size(); ++i) {
|
||||
ss << extensions[i].ToString();
|
||||
if (i != extensions.size() - 1)
|
||||
if (i != extensions.size() - 1) {
|
||||
ss << ", ";
|
||||
}
|
||||
}
|
||||
ss << ']';
|
||||
ss << '}';
|
||||
@ -42,30 +48,134 @@ std::string AudioSendStream::Config::ToString() const {
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
AudioSendStream::AudioSendStream(const webrtc::AudioSendStream::Config& config)
|
||||
: config_(config) {
|
||||
AudioSendStream::AudioSendStream(const webrtc::AudioSendStream::Config& config,
|
||||
VoiceEngine* voice_engine)
|
||||
: config_(config),
|
||||
voice_engine_(voice_engine),
|
||||
voe_base_(voice_engine) {
|
||||
LOG(LS_INFO) << "AudioSendStream: " << config_.ToString();
|
||||
RTC_DCHECK(config.voe_channel_id != -1);
|
||||
RTC_DCHECK_NE(config.voe_channel_id, -1);
|
||||
RTC_DCHECK(voice_engine_);
|
||||
}
|
||||
|
||||
AudioSendStream::~AudioSendStream() {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
LOG(LS_INFO) << "~AudioSendStream: " << config_.ToString();
|
||||
}
|
||||
|
||||
webrtc::AudioSendStream::Stats AudioSendStream::GetStats() const {
|
||||
return webrtc::AudioSendStream::Stats();
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
webrtc::AudioSendStream::Stats stats;
|
||||
stats.local_ssrc = config_.rtp.ssrc;
|
||||
ScopedVoEInterface<VoEAudioProcessing> processing(voice_engine_);
|
||||
ScopedVoEInterface<VoECodec> codec(voice_engine_);
|
||||
ScopedVoEInterface<VoERTP_RTCP> rtp(voice_engine_);
|
||||
ScopedVoEInterface<VoEVolumeControl> volume(voice_engine_);
|
||||
unsigned int ssrc = 0;
|
||||
webrtc::CallStatistics call_stats = {0};
|
||||
if (rtp->GetLocalSSRC(config_.voe_channel_id, ssrc) == -1 ||
|
||||
rtp->GetRTCPStatistics(config_.voe_channel_id, call_stats) == -1) {
|
||||
return stats;
|
||||
}
|
||||
|
||||
stats.bytes_sent = call_stats.bytesSent;
|
||||
stats.packets_sent = call_stats.packetsSent;
|
||||
|
||||
webrtc::CodecInst codec_inst = {0};
|
||||
if (codec->GetSendCodec(config_.voe_channel_id, codec_inst) != -1) {
|
||||
RTC_DCHECK_NE(codec_inst.pltype, -1);
|
||||
stats.codec_name = codec_inst.plname;
|
||||
|
||||
// Get data from the last remote RTCP report.
|
||||
std::vector<webrtc::ReportBlock> blocks;
|
||||
if (rtp->GetRemoteRTCPReportBlocks(config_.voe_channel_id, &blocks) != -1) {
|
||||
for (const webrtc::ReportBlock& block : blocks) {
|
||||
// Lookup report for send ssrc only.
|
||||
if (block.source_SSRC == stats.local_ssrc) {
|
||||
stats.packets_lost = block.cumulative_num_packets_lost;
|
||||
stats.fraction_lost = Q8ToFloat(block.fraction_lost);
|
||||
stats.ext_seqnum = block.extended_highest_sequence_number;
|
||||
// Convert samples to milliseconds.
|
||||
if (codec_inst.plfreq / 1000 > 0) {
|
||||
stats.jitter_ms =
|
||||
block.interarrival_jitter / (codec_inst.plfreq / 1000);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RTT isn't known until a RTCP report is received. Until then, VoiceEngine
|
||||
// returns 0 to indicate an error value.
|
||||
if (call_stats.rttMs > 0) {
|
||||
stats.rtt_ms = call_stats.rttMs;
|
||||
}
|
||||
|
||||
// Local speech level.
|
||||
{
|
||||
unsigned int level = 0;
|
||||
if (volume->GetSpeechInputLevelFullRange(level) != -1) {
|
||||
stats.audio_level = static_cast<int32_t>(level);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(ajm): Re-enable this metric once we have a reliable implementation.
|
||||
stats.aec_quality_min = -1;
|
||||
|
||||
bool echo_metrics_on = false;
|
||||
if (processing->GetEcMetricsStatus(echo_metrics_on) != -1 &&
|
||||
echo_metrics_on) {
|
||||
// These can also be negative, but in practice -1 is only used to signal
|
||||
// insufficient data, since the resolution is limited to multiples of 4 ms.
|
||||
int median = -1;
|
||||
int std = -1;
|
||||
float dummy = 0.0f;
|
||||
if (processing->GetEcDelayMetrics(median, std, dummy) != -1) {
|
||||
stats.echo_delay_median_ms = median;
|
||||
stats.echo_delay_std_ms = std;
|
||||
}
|
||||
|
||||
// These can take on valid negative values, so use the lowest possible level
|
||||
// as default rather than -1.
|
||||
int erl = -100;
|
||||
int erle = -100;
|
||||
int dummy1 = 0;
|
||||
int dummy2 = 0;
|
||||
if (processing->GetEchoMetrics(erl, erle, dummy1, dummy2) != -1) {
|
||||
stats.echo_return_loss = erl;
|
||||
stats.echo_return_loss_enhancement = erle;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(solenberg): Collect typing noise warnings here too!
|
||||
// bool typing_noise_detected = typing_noise_detected_;
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
const webrtc::AudioSendStream::Config& AudioSendStream::config() const {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
return config_;
|
||||
}
|
||||
|
||||
void AudioSendStream::Start() {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
}
|
||||
|
||||
void AudioSendStream::Stop() {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
}
|
||||
|
||||
void AudioSendStream::SignalNetworkState(NetworkState state) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
}
|
||||
|
||||
bool AudioSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
|
||||
// TODO(solenberg): Tests call this function on a network thread, libjingle
|
||||
// calls on the worker thread. We should move towards always using a network
|
||||
// thread. Then this check can be enabled.
|
||||
// RTC_DCHECK(!thread_checker_.CalledOnValidThread());
|
||||
return false;
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
@ -12,13 +12,20 @@
|
||||
#define WEBRTC_AUDIO_AUDIO_SEND_STREAM_H_
|
||||
|
||||
#include "webrtc/audio_send_stream.h"
|
||||
#include "webrtc/audio/scoped_voe_interface.h"
|
||||
#include "webrtc/base/thread_checker.h"
|
||||
#include "webrtc/voice_engine/include/voe_base.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class VoiceEngine;
|
||||
|
||||
namespace internal {
|
||||
|
||||
class AudioSendStream : public webrtc::AudioSendStream {
|
||||
class AudioSendStream final : public webrtc::AudioSendStream {
|
||||
public:
|
||||
explicit AudioSendStream(const webrtc::AudioSendStream::Config& config);
|
||||
AudioSendStream(const webrtc::AudioSendStream::Config& config,
|
||||
VoiceEngine* voice_engine);
|
||||
~AudioSendStream() override;
|
||||
|
||||
// webrtc::SendStream implementation.
|
||||
@ -30,12 +37,16 @@ class AudioSendStream : public webrtc::AudioSendStream {
|
||||
// webrtc::AudioSendStream implementation.
|
||||
webrtc::AudioSendStream::Stats GetStats() const override;
|
||||
|
||||
const webrtc::AudioSendStream::Config& config() const {
|
||||
return config_;
|
||||
}
|
||||
const webrtc::AudioSendStream::Config& config() const;
|
||||
|
||||
private:
|
||||
rtc::ThreadChecker thread_checker_;
|
||||
const webrtc::AudioSendStream::Config config_;
|
||||
VoiceEngine* voice_engine_;
|
||||
// We hold one interface pointer to the VoE to make sure it is kept alive.
|
||||
ScopedVoEInterface<VoEBase> voe_base_;
|
||||
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioSendStream);
|
||||
};
|
||||
} // namespace internal
|
||||
} // namespace webrtc
|
||||
|
||||
@ -11,8 +11,11 @@
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
#include "webrtc/audio/audio_send_stream.h"
|
||||
#include "webrtc/audio/conversion.h"
|
||||
#include "webrtc/test/fake_voice_engine.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
TEST(AudioSendStreamTest, ConfigToString) {
|
||||
const int kAbsSendTimeId = 3;
|
||||
@ -23,12 +26,51 @@ TEST(AudioSendStreamTest, ConfigToString) {
|
||||
config.voe_channel_id = 1;
|
||||
config.cng_payload_type = 42;
|
||||
config.red_payload_type = 17;
|
||||
EXPECT_GT(config.ToString().size(), 0u);
|
||||
EXPECT_EQ("{rtp: {ssrc: 1234, extensions: [{name: "
|
||||
"http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time, id: 3}]}, "
|
||||
"voe_channel_id: 1, cng_payload_type: 42, red_payload_type: 17}",
|
||||
config.ToString());
|
||||
}
|
||||
|
||||
TEST(AudioSendStreamTest, ConstructDestruct) {
|
||||
FakeVoiceEngine voice_engine;
|
||||
AudioSendStream::Config config(nullptr);
|
||||
config.voe_channel_id = 1;
|
||||
internal::AudioSendStream send_stream(config);
|
||||
internal::AudioSendStream send_stream(config, &voice_engine);
|
||||
}
|
||||
|
||||
TEST(AudioSendStreamTest, GetStats) {
|
||||
FakeVoiceEngine voice_engine;
|
||||
AudioSendStream::Config config(nullptr);
|
||||
config.rtp.ssrc = FakeVoiceEngine::kSendSsrc;
|
||||
config.voe_channel_id = FakeVoiceEngine::kSendChannelId;
|
||||
internal::AudioSendStream send_stream(config, &voice_engine);
|
||||
|
||||
AudioSendStream::Stats stats = send_stream.GetStats();
|
||||
const CallStatistics& call_stats = FakeVoiceEngine::kSendCallStats;
|
||||
const CodecInst& codec_inst = FakeVoiceEngine::kSendCodecInst;
|
||||
const ReportBlock& report_block = FakeVoiceEngine::kSendReportBlock;
|
||||
EXPECT_EQ(FakeVoiceEngine::kSendSsrc, stats.local_ssrc);
|
||||
EXPECT_EQ(static_cast<int64_t>(call_stats.bytesSent), stats.bytes_sent);
|
||||
EXPECT_EQ(call_stats.packetsSent, stats.packets_sent);
|
||||
EXPECT_EQ(static_cast<int32_t>(report_block.cumulative_num_packets_lost),
|
||||
stats.packets_lost);
|
||||
EXPECT_EQ(Q8ToFloat(report_block.fraction_lost), stats.fraction_lost);
|
||||
EXPECT_EQ(std::string(codec_inst.plname), stats.codec_name);
|
||||
EXPECT_EQ(static_cast<int32_t>(report_block.extended_highest_sequence_number),
|
||||
stats.ext_seqnum);
|
||||
EXPECT_EQ(static_cast<int32_t>(report_block.interarrival_jitter /
|
||||
(codec_inst.plfreq / 1000)), stats.jitter_ms);
|
||||
EXPECT_EQ(call_stats.rttMs, stats.rtt_ms);
|
||||
EXPECT_EQ(static_cast<int32_t>(FakeVoiceEngine::kSendSpeechInputLevel),
|
||||
stats.audio_level);
|
||||
EXPECT_EQ(-1, stats.aec_quality_min);
|
||||
EXPECT_EQ(FakeVoiceEngine::kSendEchoDelayMedian, stats.echo_delay_median_ms);
|
||||
EXPECT_EQ(FakeVoiceEngine::kSendEchoDelayStdDev, stats.echo_delay_std_ms);
|
||||
EXPECT_EQ(FakeVoiceEngine::kSendEchoReturnLoss, stats.echo_return_loss);
|
||||
EXPECT_EQ(FakeVoiceEngine::kSendEchoReturnLossEnhancement,
|
||||
stats.echo_return_loss_enhancement);
|
||||
EXPECT_FALSE(stats.typing_noise_detected);
|
||||
}
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
@ -13,8 +13,13 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Convert fixed point number with 8 bit fractional part, to floating point.
|
||||
inline float Q8ToFloat(uint32_t v) {
|
||||
return static_cast<float>(v) / (1 << 8);
|
||||
}
|
||||
|
||||
// Convert fixed point number with 14 bit fractional part, to floating point.
|
||||
inline float Q14ToFloat(uint16_t v) {
|
||||
inline float Q14ToFloat(uint32_t v) {
|
||||
return static_cast<float>(v) / (1 << 14);
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
||||
@ -25,7 +25,25 @@ namespace webrtc {
|
||||
|
||||
class AudioSendStream : public SendStream {
|
||||
public:
|
||||
struct Stats {};
|
||||
struct Stats {
|
||||
// TODO(solenberg): Harmonize naming and defaults with receive stream stats.
|
||||
uint32_t local_ssrc = 0;
|
||||
int64_t bytes_sent = 0;
|
||||
int32_t packets_sent = 0;
|
||||
int32_t packets_lost = -1;
|
||||
float fraction_lost = -1.0f;
|
||||
std::string codec_name;
|
||||
int32_t ext_seqnum = -1;
|
||||
int32_t jitter_ms = -1;
|
||||
int64_t rtt_ms = -1;
|
||||
int32_t audio_level = -1;
|
||||
float aec_quality_min = -1.0f;
|
||||
int32_t echo_delay_median_ms = -1;
|
||||
int32_t echo_delay_std_ms = -1;
|
||||
int32_t echo_return_loss = -100;
|
||||
int32_t echo_return_loss_enhancement = -100;
|
||||
bool typing_noise_detected = false;
|
||||
};
|
||||
|
||||
struct Config {
|
||||
Config() = delete;
|
||||
|
||||
@ -145,7 +145,6 @@ Call::Call(const Call::Config& config)
|
||||
network_enabled_(true),
|
||||
receive_crit_(RWLockWrapper::CreateRWLock()),
|
||||
send_crit_(RWLockWrapper::CreateRWLock()) {
|
||||
RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK_GE(config.bitrate_config.min_bitrate_bps, 0);
|
||||
RTC_DCHECK_GE(config.bitrate_config.start_bitrate_bps,
|
||||
config.bitrate_config.min_bitrate_bps);
|
||||
@ -199,7 +198,8 @@ webrtc::AudioSendStream* Call::CreateAudioSendStream(
|
||||
const webrtc::AudioSendStream::Config& config) {
|
||||
TRACE_EVENT0("webrtc", "Call::CreateAudioSendStream");
|
||||
RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
|
||||
AudioSendStream* send_stream = new AudioSendStream(config);
|
||||
AudioSendStream* send_stream =
|
||||
new AudioSendStream(config, config_.voice_engine);
|
||||
if (!network_enabled_)
|
||||
send_stream->SignalNetworkState(kNetworkDown);
|
||||
{
|
||||
|
||||
70
webrtc/test/fake_voice_engine.cc
Normal file
70
webrtc/test/fake_voice_engine.cc
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/test/fake_voice_engine.h"
|
||||
|
||||
namespace {
|
||||
|
||||
webrtc::AudioDecodingCallStats MakeAudioDecodingCallStats() {
|
||||
webrtc::AudioDecodingCallStats stats;
|
||||
stats.calls_to_silence_generator = 234;
|
||||
stats.calls_to_neteq = 567;
|
||||
stats.decoded_normal = 890;
|
||||
stats.decoded_plc = 123;
|
||||
stats.decoded_cng = 456;
|
||||
stats.decoded_plc_cng = 789;
|
||||
return stats;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
const int FakeVoiceEngine::kSendChannelId = 1;
|
||||
const int FakeVoiceEngine::kRecvChannelId = 2;
|
||||
const uint32_t FakeVoiceEngine::kSendSsrc = 665;
|
||||
const uint32_t FakeVoiceEngine::kRecvSsrc = 667;
|
||||
const int FakeVoiceEngine::kSendEchoDelayMedian = 254;
|
||||
const int FakeVoiceEngine::kSendEchoDelayStdDev = -3;
|
||||
const int FakeVoiceEngine::kSendEchoReturnLoss = -65;
|
||||
const int FakeVoiceEngine::kSendEchoReturnLossEnhancement = 101;
|
||||
const int FakeVoiceEngine::kRecvJitterBufferDelay = -7;
|
||||
const int FakeVoiceEngine::kRecvPlayoutBufferDelay = 302;
|
||||
const unsigned int FakeVoiceEngine::kSendSpeechInputLevel = 96;
|
||||
const unsigned int FakeVoiceEngine::kRecvSpeechOutputLevel = 99;
|
||||
|
||||
const CallStatistics FakeVoiceEngine::kSendCallStats = {
|
||||
1345, 1678, 1901, 1234, 112, 13456, 17890, 1567, -1890, -1123
|
||||
};
|
||||
|
||||
const CodecInst FakeVoiceEngine::kSendCodecInst = {
|
||||
-121, "codec_name_send", 48000, -231, -451, -671
|
||||
};
|
||||
|
||||
const ReportBlock FakeVoiceEngine::kSendReportBlock = {
|
||||
456, 780, 123, 567, 890, 132, 143, 13354
|
||||
};
|
||||
|
||||
const CallStatistics FakeVoiceEngine::kRecvCallStats = {
|
||||
345, 678, 901, 234, -12, 3456, 7890, 567, 890, 123
|
||||
};
|
||||
|
||||
const CodecInst FakeVoiceEngine::kRecvCodecInst = {
|
||||
123, "codec_name_recv", 96000, -187, -198, -103
|
||||
};
|
||||
|
||||
const NetworkStatistics FakeVoiceEngine::kRecvNetworkStats = {
|
||||
123, 456, false, 0, 0, 789, 12, 345, 678, 901, -1, -1, -1, -1, -1, 0
|
||||
};
|
||||
|
||||
const AudioDecodingCallStats FakeVoiceEngine::kRecvAudioDecodingCallStats =
|
||||
MakeAudioDecodingCallStats();
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
@ -24,12 +24,25 @@ namespace test {
|
||||
// able to get the various interfaces as usual, via T::GetInterface().
|
||||
class FakeVoiceEngine final : public VoiceEngineImpl {
|
||||
public:
|
||||
const int kSendChannelId = 1;
|
||||
const int kReceiveChannelId = 2;
|
||||
|
||||
const int kRecvJitterBufferDelay = -7;
|
||||
const int kRecvPlayoutBufferDelay = 302;
|
||||
const unsigned int kRecvSpeechOutputLevel = 99;
|
||||
static const int kSendChannelId;
|
||||
static const int kRecvChannelId;
|
||||
static const uint32_t kSendSsrc;
|
||||
static const uint32_t kRecvSsrc;
|
||||
static const int kSendEchoDelayMedian;
|
||||
static const int kSendEchoDelayStdDev;
|
||||
static const int kSendEchoReturnLoss;
|
||||
static const int kSendEchoReturnLossEnhancement;
|
||||
static const int kRecvJitterBufferDelay;
|
||||
static const int kRecvPlayoutBufferDelay;
|
||||
static const unsigned int kSendSpeechInputLevel;
|
||||
static const unsigned int kRecvSpeechOutputLevel;
|
||||
static const CallStatistics kSendCallStats;
|
||||
static const CodecInst kSendCodecInst;
|
||||
static const ReportBlock kSendReportBlock;
|
||||
static const CallStatistics kRecvCallStats;
|
||||
static const CodecInst kRecvCodecInst;
|
||||
static const NetworkStatistics kRecvNetworkStats;
|
||||
static const AudioDecodingCallStats kRecvAudioDecodingCallStats;
|
||||
|
||||
FakeVoiceEngine() : VoiceEngineImpl(new Config(), true) {
|
||||
// Increase ref count so this object isn't automatically deleted whenever
|
||||
@ -42,39 +55,83 @@ class FakeVoiceEngine final : public VoiceEngineImpl {
|
||||
--_ref_count;
|
||||
}
|
||||
|
||||
const CallStatistics& GetRecvCallStats() const {
|
||||
static const CallStatistics kStats = {
|
||||
345, 678, 901, 234, -1, 0, 0, 567, 890, 123
|
||||
};
|
||||
return kStats;
|
||||
// VoEAudioProcessing
|
||||
int SetNsStatus(bool enable, NsModes mode = kNsUnchanged) override {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const CodecInst& GetRecvRecCodecInst() const {
|
||||
static const CodecInst kStats = {
|
||||
123, "codec_name", 96000, -1, -1, -1
|
||||
};
|
||||
return kStats;
|
||||
int GetNsStatus(bool& enabled, NsModes& mode) override { return -1; }
|
||||
int SetAgcStatus(bool enable, AgcModes mode = kAgcUnchanged) override {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const NetworkStatistics& GetRecvNetworkStats() const {
|
||||
static const NetworkStatistics kStats = {
|
||||
123, 456, false, 0, 0, 789, 12, 345, 678, 901, -1, -1, -1, -1, -1, 0
|
||||
};
|
||||
return kStats;
|
||||
int GetAgcStatus(bool& enabled, AgcModes& mode) override { return -1; }
|
||||
int SetAgcConfig(AgcConfig config) override { return -1; }
|
||||
int GetAgcConfig(AgcConfig& config) override { return -1; }
|
||||
int SetEcStatus(bool enable, EcModes mode = kEcUnchanged) override {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const AudioDecodingCallStats& GetRecvAudioDecodingCallStats() const {
|
||||
static AudioDecodingCallStats stats;
|
||||
if (stats.calls_to_silence_generator == 0) {
|
||||
stats.calls_to_silence_generator = 234;
|
||||
stats.calls_to_neteq = 567;
|
||||
stats.decoded_normal = 890;
|
||||
stats.decoded_plc = 123;
|
||||
stats.decoded_cng = 456;
|
||||
stats.decoded_plc_cng = 789;
|
||||
}
|
||||
return stats;
|
||||
int GetEcStatus(bool& enabled, EcModes& mode) override { return -1; }
|
||||
int EnableDriftCompensation(bool enable) override { return -1; }
|
||||
bool DriftCompensationEnabled() override { return false; }
|
||||
void SetDelayOffsetMs(int offset) override {}
|
||||
int DelayOffsetMs() override { return -1; }
|
||||
int SetAecmMode(AecmModes mode = kAecmSpeakerphone,
|
||||
bool enableCNG = true) override { return -1; }
|
||||
int GetAecmMode(AecmModes& mode, bool& enabledCNG) override { return -1; }
|
||||
int EnableHighPassFilter(bool enable) override { return -1; }
|
||||
bool IsHighPassFilterEnabled() override { return false; }
|
||||
int SetRxNsStatus(int channel,
|
||||
bool enable,
|
||||
NsModes mode = kNsUnchanged) override { return -1; }
|
||||
int GetRxNsStatus(int channel, bool& enabled, NsModes& mode) override {
|
||||
return -1;
|
||||
}
|
||||
int SetRxAgcStatus(int channel,
|
||||
bool enable,
|
||||
AgcModes mode = kAgcUnchanged) override { return -1; }
|
||||
int GetRxAgcStatus(int channel, bool& enabled, AgcModes& mode) override {
|
||||
return -1;
|
||||
}
|
||||
int SetRxAgcConfig(int channel, AgcConfig config) override { return -1; }
|
||||
int GetRxAgcConfig(int channel, AgcConfig& config) override { return -1; }
|
||||
int RegisterRxVadObserver(int channel,
|
||||
VoERxVadCallback& observer) override { return -1; }
|
||||
int DeRegisterRxVadObserver(int channel) override { return -1; }
|
||||
int VoiceActivityIndicator(int channel) override { return -1; }
|
||||
int SetEcMetricsStatus(bool enable) override { return -1; }
|
||||
int GetEcMetricsStatus(bool& enabled) override {
|
||||
enabled = true;
|
||||
return 0;
|
||||
}
|
||||
int GetEchoMetrics(int& ERL, int& ERLE, int& RERL, int& A_NLP) override {
|
||||
ERL = kSendEchoReturnLoss;
|
||||
ERLE = kSendEchoReturnLossEnhancement;
|
||||
RERL = -123456789;
|
||||
A_NLP = 123456789;
|
||||
return 0;
|
||||
}
|
||||
int GetEcDelayMetrics(int& delay_median,
|
||||
int& delay_std,
|
||||
float& fraction_poor_delays) override {
|
||||
delay_median = kSendEchoDelayMedian;
|
||||
delay_std = kSendEchoDelayStdDev;
|
||||
fraction_poor_delays = -12345.7890f;
|
||||
return 0;
|
||||
}
|
||||
int StartDebugRecording(const char* fileNameUTF8) override { return -1; }
|
||||
int StartDebugRecording(FILE* file_handle) override { return -1; }
|
||||
int StopDebugRecording() override { return -1; }
|
||||
int SetTypingDetectionStatus(bool enable) override { return -1; }
|
||||
int GetTypingDetectionStatus(bool& enabled) override { return -1; }
|
||||
int TimeSinceLastTyping(int& seconds) override { return -1; }
|
||||
int SetTypingDetectionParameters(int timeWindow,
|
||||
int costPerTyping,
|
||||
int reportingThreshold,
|
||||
int penaltyDecay,
|
||||
int typeEventDelay = 0) override {
|
||||
return -1;
|
||||
}
|
||||
void EnableStereoChannelSwapping(bool enable) override {}
|
||||
bool IsStereoChannelSwappingEnabled() override { return false; }
|
||||
|
||||
// VoEBase
|
||||
int RegisterVoiceEngineObserver(VoiceEngineObserver& observer) override {
|
||||
@ -105,11 +162,15 @@ class FakeVoiceEngine final : public VoiceEngineImpl {
|
||||
int NumOfCodecs() override { return -1; }
|
||||
int GetCodec(int index, CodecInst& codec) override { return -1; }
|
||||
int SetSendCodec(int channel, const CodecInst& codec) override { return -1; }
|
||||
int GetSendCodec(int channel, CodecInst& codec) override { return -1; }
|
||||
int GetSendCodec(int channel, CodecInst& codec) override {
|
||||
EXPECT_EQ(channel, kSendChannelId);
|
||||
codec = kSendCodecInst;
|
||||
return 0;
|
||||
}
|
||||
int SetBitRate(int channel, int bitrate_bps) override { return -1; }
|
||||
int GetRecCodec(int channel, CodecInst& codec) override {
|
||||
EXPECT_EQ(channel, kReceiveChannelId);
|
||||
codec = GetRecvRecCodecInst();
|
||||
EXPECT_EQ(channel, kRecvChannelId);
|
||||
codec = kRecvCodecInst;
|
||||
return 0;
|
||||
}
|
||||
int SetRecPayloadType(int channel, const CodecInst& codec) override {
|
||||
@ -295,23 +356,27 @@ class FakeVoiceEngine final : public VoiceEngineImpl {
|
||||
|
||||
// VoENetEqStats
|
||||
int GetNetworkStatistics(int channel, NetworkStatistics& stats) override {
|
||||
EXPECT_EQ(channel, kReceiveChannelId);
|
||||
stats = GetRecvNetworkStats();
|
||||
EXPECT_EQ(channel, kRecvChannelId);
|
||||
stats = kRecvNetworkStats;
|
||||
return 0;
|
||||
}
|
||||
int GetDecodingCallStatistics(int channel,
|
||||
AudioDecodingCallStats* stats) const override {
|
||||
EXPECT_EQ(channel, kReceiveChannelId);
|
||||
EXPECT_EQ(channel, kRecvChannelId);
|
||||
EXPECT_NE(nullptr, stats);
|
||||
*stats = GetRecvAudioDecodingCallStats();
|
||||
*stats = kRecvAudioDecodingCallStats;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// VoERTP_RTCP
|
||||
int SetLocalSSRC(int channel, unsigned int ssrc) override { return -1; }
|
||||
int GetLocalSSRC(int channel, unsigned int& ssrc) override { return -1; }
|
||||
int GetLocalSSRC(int channel, unsigned int& ssrc) override {
|
||||
EXPECT_EQ(channel, kSendChannelId);
|
||||
ssrc = 0;
|
||||
return 0;
|
||||
}
|
||||
int GetRemoteSSRC(int channel, unsigned int& ssrc) override {
|
||||
EXPECT_EQ(channel, kReceiveChannelId);
|
||||
EXPECT_EQ(channel, kRecvChannelId);
|
||||
ssrc = 0;
|
||||
return 0;
|
||||
}
|
||||
@ -347,13 +412,28 @@ class FakeVoiceEngine final : public VoiceEngineImpl {
|
||||
unsigned int& maxJitterMs,
|
||||
unsigned int& discardedPackets) override { return -1; }
|
||||
int GetRTCPStatistics(int channel, CallStatistics& stats) override {
|
||||
EXPECT_EQ(channel, kReceiveChannelId);
|
||||
stats = GetRecvCallStats();
|
||||
if (channel == kSendChannelId) {
|
||||
stats = kSendCallStats;
|
||||
} else {
|
||||
EXPECT_EQ(channel, kRecvChannelId);
|
||||
stats = kRecvCallStats;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int GetRemoteRTCPReportBlocks(
|
||||
int channel,
|
||||
std::vector<ReportBlock>* receive_blocks) override { return -1; }
|
||||
std::vector<ReportBlock>* receive_blocks) override {
|
||||
EXPECT_EQ(channel, kSendChannelId);
|
||||
EXPECT_NE(receive_blocks, nullptr);
|
||||
EXPECT_EQ(receive_blocks->size(), 0u);
|
||||
webrtc::ReportBlock block = kSendReportBlock;
|
||||
receive_blocks->push_back(block); // Has wrong SSRC.
|
||||
block.source_SSRC = kSendSsrc;
|
||||
receive_blocks->push_back(block); // Correct block.
|
||||
block.fraction_lost = 0;
|
||||
receive_blocks->push_back(block); // Duplicate SSRC, bad fraction_lost.
|
||||
return 0;
|
||||
}
|
||||
int SetNACKStatus(int channel, bool enable, int maxNoPackets) override {
|
||||
return -1;
|
||||
}
|
||||
@ -365,7 +445,7 @@ class FakeVoiceEngine final : public VoiceEngineImpl {
|
||||
int GetDelayEstimate(int channel,
|
||||
int* jitter_buffer_delay_ms,
|
||||
int* playout_buffer_delay_ms) override {
|
||||
EXPECT_EQ(channel, kReceiveChannelId);
|
||||
EXPECT_EQ(channel, kRecvChannelId);
|
||||
*jitter_buffer_delay_ms = kRecvJitterBufferDelay;
|
||||
*playout_buffer_delay_ms = kRecvPlayoutBufferDelay;
|
||||
return 0;
|
||||
@ -395,10 +475,13 @@ class FakeVoiceEngine final : public VoiceEngineImpl {
|
||||
int GetSpeechOutputLevel(int channel, unsigned int& level) override {
|
||||
return -1;
|
||||
}
|
||||
int GetSpeechInputLevelFullRange(unsigned int& level) override { return -1; }
|
||||
int GetSpeechInputLevelFullRange(unsigned int& level) override {
|
||||
level = kSendSpeechInputLevel;
|
||||
return 0;
|
||||
}
|
||||
int GetSpeechOutputLevelFullRange(int channel,
|
||||
unsigned int& level) override {
|
||||
EXPECT_EQ(channel, kReceiveChannelId);
|
||||
EXPECT_EQ(channel, kRecvChannelId);
|
||||
level = kRecvSpeechOutputLevel;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
'fake_encoder.h',
|
||||
'fake_network_pipe.cc',
|
||||
'fake_network_pipe.h',
|
||||
'fake_voice_engine.cc',
|
||||
'fake_voice_engine.h',
|
||||
'frame_generator_capturer.cc',
|
||||
'frame_generator_capturer.h',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user