OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/audio/audio_receive_stream.h" | 11 #include "webrtc/audio/audio_receive_stream.h" |
12 | 12 |
13 #include <string> | 13 #include <string> |
14 | 14 |
15 #include "webrtc/base/checks.h" | 15 #include "webrtc/base/checks.h" |
16 #include "webrtc/base/logging.h" | 16 #include "webrtc/base/logging.h" |
17 #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimat or.h" | 17 #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimat or.h" |
18 #include "webrtc/system_wrappers/interface/tick_util.h" | 18 #include "webrtc/system_wrappers/interface/tick_util.h" |
19 #include "webrtc/voice_engine/include/voe_base.h" | |
20 #include "webrtc/voice_engine/include/voe_codec.h" | |
21 #include "webrtc/voice_engine/include/voe_neteq_stats.h" | |
22 #include "webrtc/voice_engine/include/voe_rtp_rtcp.h" | |
23 #include "webrtc/voice_engine/include/voe_video_sync.h" | |
24 #include "webrtc/voice_engine/include/voe_volume_control.h" | |
25 | |
26 namespace { | |
27 template<class T> class scoped_voe_interface { | |
tommi
2015/10/19 12:36:24
nit: ScopedVoEInterface
(I know you're following t
the sun
2015/10/19 14:25:02
Done.
| |
28 public: | |
29 explicit scoped_voe_interface(webrtc::VoiceEngine* e) : ptr(nullptr) { | |
30 RTC_DCHECK(e); | |
31 ptr = T::GetInterface(e); | |
tommi
2015/10/19 12:36:24
call T::GetInterface(e) in the initializer list
the sun
2015/10/19 14:25:02
Done.
| |
32 } | |
33 ~scoped_voe_interface() { | |
34 if (ptr) ptr->Release(); | |
tommi
2015/10/19 12:36:24
nit: two lines
the sun
2015/10/19 14:25:02
Done.
| |
35 } | |
36 T* operator->() { | |
37 RTC_DCHECK(ptr); | |
38 return ptr; | |
39 } | |
40 private: | |
41 T* ptr; | |
tommi
2015/10/19 12:36:24
ptr_
the sun
2015/10/19 14:25:02
Done.
| |
42 }; | |
43 } // namespace { | |
19 | 44 |
20 namespace webrtc { | 45 namespace webrtc { |
21 std::string AudioReceiveStream::Config::Rtp::ToString() const { | 46 std::string AudioReceiveStream::Config::Rtp::ToString() const { |
22 std::stringstream ss; | 47 std::stringstream ss; |
23 ss << "{remote_ssrc: " << remote_ssrc; | 48 ss << "{remote_ssrc: " << remote_ssrc; |
24 ss << ", extensions: ["; | 49 ss << ", extensions: ["; |
25 for (size_t i = 0; i < extensions.size(); ++i) { | 50 for (size_t i = 0; i < extensions.size(); ++i) { |
26 ss << extensions[i].ToString(); | 51 ss << extensions[i].ToString(); |
27 if (i != extensions.size() - 1) | 52 if (i != extensions.size() - 1) |
28 ss << ", "; | 53 ss << ", "; |
29 } | 54 } |
30 ss << ']'; | 55 ss << ']'; |
31 ss << '}'; | 56 ss << '}'; |
32 return ss.str(); | 57 return ss.str(); |
33 } | 58 } |
34 | 59 |
35 std::string AudioReceiveStream::Config::ToString() const { | 60 std::string AudioReceiveStream::Config::ToString() const { |
36 std::stringstream ss; | 61 std::stringstream ss; |
37 ss << "{rtp: " << rtp.ToString(); | 62 ss << "{rtp: " << rtp.ToString(); |
38 ss << ", voe_channel_id: " << voe_channel_id; | 63 ss << ", voe_channel_id: " << voe_channel_id; |
39 if (!sync_group.empty()) | 64 if (!sync_group.empty()) |
40 ss << ", sync_group: " << sync_group; | 65 ss << ", sync_group: " << sync_group; |
41 ss << '}'; | 66 ss << '}'; |
42 return ss.str(); | 67 return ss.str(); |
43 } | 68 } |
44 | 69 |
45 namespace internal { | 70 namespace internal { |
46 AudioReceiveStream::AudioReceiveStream( | 71 AudioReceiveStream::AudioReceiveStream( |
47 RemoteBitrateEstimator* remote_bitrate_estimator, | 72 RemoteBitrateEstimator* remote_bitrate_estimator, |
48 const webrtc::AudioReceiveStream::Config& config) | 73 const webrtc::AudioReceiveStream::Config& config, |
74 VoiceEngine* voice_engine) | |
49 : remote_bitrate_estimator_(remote_bitrate_estimator), | 75 : remote_bitrate_estimator_(remote_bitrate_estimator), |
50 config_(config), | 76 config_(config), |
77 voice_engine_(voice_engine), | |
51 rtp_header_parser_(RtpHeaderParser::Create()) { | 78 rtp_header_parser_(RtpHeaderParser::Create()) { |
52 LOG(LS_INFO) << "AudioReceiveStream: " << config_.ToString(); | 79 LOG(LS_INFO) << "AudioReceiveStream: " << config_.ToString(); |
53 RTC_DCHECK(config.voe_channel_id != -1); | 80 RTC_DCHECK(config.voe_channel_id != -1); |
54 RTC_DCHECK(remote_bitrate_estimator_ != nullptr); | 81 RTC_DCHECK(remote_bitrate_estimator_ != nullptr); |
82 RTC_DCHECK(voice_engine_ != nullptr); | |
55 RTC_DCHECK(rtp_header_parser_ != nullptr); | 83 RTC_DCHECK(rtp_header_parser_ != nullptr); |
56 for (const auto& ext : config.rtp.extensions) { | 84 for (const auto& ext : config.rtp.extensions) { |
57 // One-byte-extension local identifiers are in the range 1-14 inclusive. | 85 // One-byte-extension local identifiers are in the range 1-14 inclusive. |
58 RTC_DCHECK_GE(ext.id, 1); | 86 RTC_DCHECK_GE(ext.id, 1); |
59 RTC_DCHECK_LE(ext.id, 14); | 87 RTC_DCHECK_LE(ext.id, 14); |
60 if (ext.name == RtpExtension::kAudioLevel) { | 88 if (ext.name == RtpExtension::kAudioLevel) { |
61 RTC_CHECK(rtp_header_parser_->RegisterRtpHeaderExtension( | 89 RTC_CHECK(rtp_header_parser_->RegisterRtpHeaderExtension( |
62 kRtpExtensionAudioLevel, ext.id)); | 90 kRtpExtensionAudioLevel, ext.id)); |
63 } else if (ext.name == RtpExtension::kAbsSendTime) { | 91 } else if (ext.name == RtpExtension::kAbsSendTime) { |
64 RTC_CHECK(rtp_header_parser_->RegisterRtpHeaderExtension( | 92 RTC_CHECK(rtp_header_parser_->RegisterRtpHeaderExtension( |
65 kRtpExtensionAbsoluteSendTime, ext.id)); | 93 kRtpExtensionAbsoluteSendTime, ext.id)); |
66 } else if (ext.name == RtpExtension::kTransportSequenceNumber) { | 94 } else if (ext.name == RtpExtension::kTransportSequenceNumber) { |
67 RTC_CHECK(rtp_header_parser_->RegisterRtpHeaderExtension( | 95 RTC_CHECK(rtp_header_parser_->RegisterRtpHeaderExtension( |
68 kRtpExtensionTransportSequenceNumber, ext.id)); | 96 kRtpExtensionTransportSequenceNumber, ext.id)); |
69 } else { | 97 } else { |
70 RTC_NOTREACHED() << "Unsupported RTP extension."; | 98 RTC_NOTREACHED() << "Unsupported RTP extension."; |
71 } | 99 } |
72 } | 100 } |
73 } | 101 } |
74 | 102 |
75 AudioReceiveStream::~AudioReceiveStream() { | 103 AudioReceiveStream::~AudioReceiveStream() { |
76 LOG(LS_INFO) << "~AudioReceiveStream: " << config_.ToString(); | 104 LOG(LS_INFO) << "~AudioReceiveStream: " << config_.ToString(); |
77 } | 105 } |
78 | 106 |
79 webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const { | 107 webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const { |
tommi
2015/10/19 12:36:24
Thread check?
the sun
2015/10/19 14:25:02
Done.
| |
80 return webrtc::AudioReceiveStream::Stats(); | 108 webrtc::AudioReceiveStream::Stats stats; |
109 stats.remote_ssrc = config_.rtp.remote_ssrc; | |
110 scoped_voe_interface<VoECodec> codec(voice_engine_); | |
111 scoped_voe_interface<VoENetEqStats> neteq(voice_engine_); | |
112 scoped_voe_interface<VoERTP_RTCP> rtp(voice_engine_); | |
113 scoped_voe_interface<VoEVideoSync> sync(voice_engine_); | |
114 scoped_voe_interface<VoEVolumeControl> volume(voice_engine_); | |
115 unsigned int ssrc = 0; | |
tommi
2015/10/19 12:36:24
do we always use unsigned int for ssrc? do you kn
the sun
2015/10/19 14:25:02
We're pretty consistent with uint32_t for ssrcs. T
| |
116 webrtc::CallStatistics cs = {0}; | |
117 webrtc::CodecInst ci = {0}; | |
118 // Only collect stats if we have seen some traffic with the SSRC. | |
119 if (rtp->GetRemoteSSRC(config_.voe_channel_id, ssrc) != -1 && | |
120 rtp->GetRTCPStatistics(config_.voe_channel_id, cs) != -1 && | |
121 codec->GetRecCodec(config_.voe_channel_id, ci) != -1) { | |
tommi
2015/10/19 12:36:24
nit: could we convert this to an early return inst
the sun
2015/10/19 14:25:02
Done.
| |
122 stats.bytes_rcvd = cs.bytesReceived; | |
123 stats.packets_rcvd = cs.packetsReceived; | |
124 stats.packets_lost = cs.cumulativeLost; | |
125 stats.fraction_lost = static_cast<float>(cs.fractionLost) / (1 << 8); | |
126 if (ci.pltype != -1) { | |
tommi
2015/10/19 12:36:24
no {} (and below for single line if()s)
the sun
2015/10/19 14:25:02
please, point me to the style guide if I've missed
tommi
2015/10/19 14:55:44
Consistency. All I did was go up a few lines to se
the sun
2015/10/20 08:31:29
Oops, touché. Fixed that. Blaming sloppy copy+past
| |
127 stats.codec_name = ci.plname; | |
128 } | |
129 | |
130 stats.ext_seqnum = cs.extendedMax; | |
131 if (ci.plfreq / 1000 > 0) { | |
132 stats.jitter_ms = cs.jitterSamples / (ci.plfreq / 1000); | |
133 } | |
134 { | |
135 int jitter_buffer_delay_ms = 0; | |
136 int playout_buffer_delay_ms = 0; | |
137 sync->GetDelayEstimate(config_.voe_channel_id, &jitter_buffer_delay_ms, | |
138 &playout_buffer_delay_ms); | |
139 stats.delay_estimate_ms = | |
140 jitter_buffer_delay_ms + playout_buffer_delay_ms; | |
141 } | |
142 { | |
143 unsigned int level = 0; | |
tommi
2015/10/19 12:36:24
in some places we use uint32_t for this, but appar
the sun
2015/10/19 14:25:02
Yes, I consistently use the types specified in the
| |
144 if (volume->GetSpeechOutputLevelFullRange(config_.voe_channel_id, level) | |
145 != -1) { | |
146 stats.audio_level = level; | |
tommi
2015/10/19 12:36:24
I wonder which type audio_level is
the sun
2015/10/19 14:25:02
Done.
| |
147 }; | |
tommi
2015/10/19 12:36:24
no ;
the sun
2015/10/19 14:25:02
thx
| |
148 } | |
149 | |
150 webrtc::NetworkStatistics ns = {0}; | |
151 if (neteq->GetNetworkStatistics(config_.voe_channel_id, ns) != -1) { | |
152 // Get jitter buffer and total delay (alg + jitter + playout) stats. | |
153 stats.jitter_buffer_ms = ns.currentBufferSize; | |
154 stats.jitter_buffer_preferred_ms = ns.preferredBufferSize; | |
155 stats.expand_rate = | |
156 static_cast<float>(ns.currentExpandRate) / (1 << 14); | |
tommi
2015/10/19 12:36:24
can you add a note why we divide all the rates by
the sun
2015/10/19 14:25:02
Sure: https://code.google.com/p/chromium/codesearc
| |
157 stats.speech_expand_rate = | |
158 static_cast<float>(ns.currentSpeechExpandRate) / (1 << 14); | |
159 stats.secondary_decoded_rate = | |
160 static_cast<float>(ns.currentSecondaryDecodedRate) / (1 << 14); | |
161 stats.accelerate_rate = | |
162 static_cast<float>(ns.currentAccelerateRate) / (1 << 14); | |
163 stats.preemptive_expand_rate = | |
164 static_cast<float>(ns.currentPreemptiveRate) / (1 << 14); | |
165 } | |
166 | |
167 webrtc::AudioDecodingCallStats ds; | |
168 if (neteq->GetDecodingCallStatistics(config_.voe_channel_id, &ds) != -1) { | |
169 stats.decoding_calls_to_silence_generator = | |
170 ds.calls_to_silence_generator; | |
171 stats.decoding_calls_to_neteq = ds.calls_to_neteq; | |
172 stats.decoding_normal = ds.decoded_normal; | |
173 stats.decoding_plc = ds.decoded_plc; | |
174 stats.decoding_cng = ds.decoded_cng; | |
175 stats.decoding_plc_cng = ds.decoded_plc_cng; | |
176 } | |
177 | |
178 stats.capture_start_ntp_time_ms = cs.capture_start_ntp_time_ms_; | |
179 } | |
180 return stats; | |
81 } | 181 } |
82 | 182 |
83 const webrtc::AudioReceiveStream::Config& AudioReceiveStream::config() const { | 183 const webrtc::AudioReceiveStream::Config& AudioReceiveStream::config() const { |
84 return config_; | 184 return config_; |
85 } | 185 } |
86 | 186 |
87 void AudioReceiveStream::Start() { | 187 void AudioReceiveStream::Start() { |
88 } | 188 } |
89 | 189 |
90 void AudioReceiveStream::Stop() { | 190 void AudioReceiveStream::Stop() { |
(...skipping 23 matching lines...) Expand all Loading... | |
114 if (packet_time.timestamp >= 0) | 214 if (packet_time.timestamp >= 0) |
115 arrival_time_ms = (packet_time.timestamp + 500) / 1000; | 215 arrival_time_ms = (packet_time.timestamp + 500) / 1000; |
116 size_t payload_size = length - header.headerLength; | 216 size_t payload_size = length - header.headerLength; |
117 remote_bitrate_estimator_->IncomingPacket(arrival_time_ms, payload_size, | 217 remote_bitrate_estimator_->IncomingPacket(arrival_time_ms, payload_size, |
118 header, false); | 218 header, false); |
119 } | 219 } |
120 return true; | 220 return true; |
121 } | 221 } |
122 } // namespace internal | 222 } // namespace internal |
123 } // namespace webrtc | 223 } // namespace webrtc |
OLD | NEW |