Index: webrtc/audio/audio_send_stream.cc |
diff --git a/webrtc/audio/audio_send_stream.cc b/webrtc/audio/audio_send_stream.cc |
index 0d0c072bf4a58fd94ac82639a439530afc5bea5a..1729cb9c291ad5f76d7c53c079f63c2f00419c97 100644 |
--- a/webrtc/audio/audio_send_stream.cc |
+++ b/webrtc/audio/audio_send_stream.cc |
@@ -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(voice_engine_ != nullptr); |
kwiberg-webrtc
2015/10/26 13:19:53
Just RTC_DCHECK(voice_engine_);? Otherwise, RTC_DC
the sun
2015/10/26 14:44:02
Done.
|
} |
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(codec_inst.pltype != -1); |
kwiberg-webrtc
2015/10/26 13:19:53
RTC_DCHECK_NE
the sun
2015/10/26 14:44:02
Done.
|
+ 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. |
kwiberg-webrtc
2015/10/26 13:19:53
:-)
the sun
2015/10/26 14:44:02
This is actually copy+paste. There's some likeliho
|
+ 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. |
kwiberg-webrtc
2015/10/26 13:19:53
:-)
the sun
2015/10/26 14:44:02
Acknowledged.
|
+ 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 |