Line data Source code
1 : /*
2 : * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 : *
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
6 : * tree. An additional intellectual property rights grant can be found
7 : * in the file PATENTS. All contributing project authors may
8 : * be found in the AUTHORS file in the root of the source tree.
9 : */
10 :
11 : #include "webrtc/audio/audio_receive_stream.h"
12 :
13 : #include <string>
14 : #include <utility>
15 :
16 : #include "webrtc/api/call/audio_sink.h"
17 : #include "webrtc/audio/audio_send_stream.h"
18 : #include "webrtc/audio/audio_state.h"
19 : #include "webrtc/audio/conversion.h"
20 : #include "webrtc/base/checks.h"
21 : #include "webrtc/base/logging.h"
22 : #include "webrtc/base/timeutils.h"
23 : #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
24 : #include "webrtc/voice_engine/channel_proxy.h"
25 : #include "webrtc/voice_engine/include/voe_base.h"
26 : #include "webrtc/voice_engine/include/voe_codec.h"
27 : #include "webrtc/voice_engine/include/voe_neteq_stats.h"
28 : #include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
29 : #include "webrtc/voice_engine/include/voe_video_sync.h"
30 : #include "webrtc/voice_engine/include/voe_volume_control.h"
31 : #include "webrtc/voice_engine/voice_engine_impl.h"
32 :
33 : namespace webrtc {
34 :
35 0 : std::string AudioReceiveStream::Config::Rtp::ToString() const {
36 0 : std::stringstream ss;
37 0 : ss << "{remote_ssrc: " << remote_ssrc;
38 0 : ss << ", local_ssrc: " << local_ssrc;
39 0 : ss << ", transport_cc: " << (transport_cc ? "on" : "off");
40 0 : ss << ", nack: " << nack.ToString();
41 0 : ss << ", extensions: [";
42 0 : for (size_t i = 0; i < extensions.size(); ++i) {
43 0 : ss << extensions[i].ToString();
44 0 : if (i != extensions.size() - 1) {
45 0 : ss << ", ";
46 : }
47 : }
48 0 : ss << ']';
49 0 : ss << '}';
50 0 : return ss.str();
51 : }
52 :
53 0 : std::string AudioReceiveStream::Config::ToString() const {
54 0 : std::stringstream ss;
55 0 : ss << "{rtp: " << rtp.ToString();
56 : ss << ", rtcp_send_transport: "
57 0 : << (rtcp_send_transport ? "(Transport)" : "nullptr");
58 0 : ss << ", voe_channel_id: " << voe_channel_id;
59 0 : if (!sync_group.empty()) {
60 0 : ss << ", sync_group: " << sync_group;
61 : }
62 0 : ss << '}';
63 0 : return ss.str();
64 : }
65 :
66 : namespace internal {
67 0 : AudioReceiveStream::AudioReceiveStream(
68 : PacketRouter* packet_router,
69 : RemoteBitrateEstimator* remote_bitrate_estimator,
70 : const webrtc::AudioReceiveStream::Config& config,
71 : const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
72 0 : webrtc::RtcEventLog* event_log)
73 : : remote_bitrate_estimator_(remote_bitrate_estimator),
74 : config_(config),
75 : audio_state_(audio_state),
76 0 : rtp_header_parser_(RtpHeaderParser::Create()) {
77 0 : LOG(LS_INFO) << "AudioReceiveStream: " << config_.ToString();
78 0 : RTC_DCHECK_NE(config_.voe_channel_id, -1);
79 0 : RTC_DCHECK(audio_state_.get());
80 0 : RTC_DCHECK(packet_router);
81 0 : RTC_DCHECK(remote_bitrate_estimator);
82 0 : RTC_DCHECK(rtp_header_parser_);
83 :
84 0 : VoiceEngineImpl* voe_impl = static_cast<VoiceEngineImpl*>(voice_engine());
85 0 : channel_proxy_ = voe_impl->GetChannelProxy(config_.voe_channel_id);
86 0 : channel_proxy_->SetRtcEventLog(event_log);
87 0 : channel_proxy_->SetLocalSSRC(config.rtp.local_ssrc);
88 : // TODO(solenberg): Config NACK history window (which is a packet count),
89 : // using the actual packet size for the configured codec.
90 0 : channel_proxy_->SetNACKStatus(config_.rtp.nack.rtp_history_ms != 0,
91 0 : config_.rtp.nack.rtp_history_ms / 20);
92 :
93 : // TODO(ossu): This is where we'd like to set the decoder factory to
94 : // use. However, since it needs to be included when constructing Channel, we
95 : // cannot do that until we're able to move Channel ownership into the
96 : // Audio{Send,Receive}Streams. The best we can do is check that we're not
97 : // trying to use two different factories using the different interfaces.
98 0 : RTC_CHECK(config.decoder_factory);
99 0 : RTC_CHECK_EQ(config.decoder_factory,
100 0 : channel_proxy_->GetAudioDecoderFactory());
101 :
102 0 : channel_proxy_->RegisterExternalTransport(config.rtcp_send_transport);
103 :
104 0 : for (const auto& extension : config.rtp.extensions) {
105 0 : if (extension.uri == RtpExtension::kAudioLevelUri) {
106 0 : channel_proxy_->SetReceiveAudioLevelIndicationStatus(true, extension.id);
107 0 : bool registered = rtp_header_parser_->RegisterRtpHeaderExtension(
108 0 : kRtpExtensionAudioLevel, extension.id);
109 0 : RTC_DCHECK(registered);
110 0 : } else if (extension.uri == RtpExtension::kTransportSequenceNumberUri) {
111 0 : channel_proxy_->EnableReceiveTransportSequenceNumber(extension.id);
112 0 : bool registered = rtp_header_parser_->RegisterRtpHeaderExtension(
113 0 : kRtpExtensionTransportSequenceNumber, extension.id);
114 0 : RTC_DCHECK(registered);
115 : } else {
116 0 : RTC_NOTREACHED() << "Unsupported RTP extension.";
117 : }
118 : }
119 : // Configure bandwidth estimation.
120 0 : channel_proxy_->RegisterReceiverCongestionControlObjects(packet_router);
121 0 : }
122 :
123 0 : AudioReceiveStream::~AudioReceiveStream() {
124 0 : RTC_DCHECK_RUN_ON(&thread_checker_);
125 0 : LOG(LS_INFO) << "~AudioReceiveStream: " << config_.ToString();
126 0 : if (playing_) {
127 0 : Stop();
128 : }
129 0 : channel_proxy_->DisassociateSendChannel();
130 0 : channel_proxy_->DeRegisterExternalTransport();
131 0 : channel_proxy_->ResetCongestionControlObjects();
132 0 : channel_proxy_->SetRtcEventLog(nullptr);
133 0 : remote_bitrate_estimator_->RemoveStream(config_.rtp.remote_ssrc);
134 0 : }
135 :
136 0 : void AudioReceiveStream::Start() {
137 0 : RTC_DCHECK_RUN_ON(&thread_checker_);
138 0 : if (playing_) {
139 0 : return;
140 : }
141 :
142 0 : int error = SetVoiceEnginePlayout(true);
143 0 : if (error != 0) {
144 0 : LOG(LS_ERROR) << "AudioReceiveStream::Start failed with error: " << error;
145 0 : return;
146 : }
147 :
148 0 : if (!audio_state()->mixer()->AddSource(this)) {
149 0 : LOG(LS_ERROR) << "Failed to add source to mixer.";
150 0 : SetVoiceEnginePlayout(false);
151 0 : return;
152 : }
153 :
154 0 : playing_ = true;
155 : }
156 :
157 0 : void AudioReceiveStream::Stop() {
158 0 : RTC_DCHECK_RUN_ON(&thread_checker_);
159 0 : if (!playing_) {
160 0 : return;
161 : }
162 0 : playing_ = false;
163 :
164 0 : audio_state()->mixer()->RemoveSource(this);
165 0 : SetVoiceEnginePlayout(false);
166 : }
167 :
168 0 : webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
169 0 : RTC_DCHECK_RUN_ON(&thread_checker_);
170 0 : webrtc::AudioReceiveStream::Stats stats;
171 0 : stats.remote_ssrc = config_.rtp.remote_ssrc;
172 0 : ScopedVoEInterface<VoECodec> codec(voice_engine());
173 :
174 0 : webrtc::CallStatistics call_stats = channel_proxy_->GetRTCPStatistics();
175 0 : webrtc::CodecInst codec_inst = {0};
176 0 : if (codec->GetRecCodec(config_.voe_channel_id, codec_inst) == -1) {
177 0 : return stats;
178 : }
179 :
180 0 : stats.bytes_rcvd = call_stats.bytesReceived;
181 0 : stats.packets_rcvd = call_stats.packetsReceived;
182 0 : stats.packets_lost = call_stats.cumulativeLost;
183 0 : stats.fraction_lost = Q8ToFloat(call_stats.fractionLost);
184 0 : stats.capture_start_ntp_time_ms = call_stats.capture_start_ntp_time_ms_;
185 0 : if (codec_inst.pltype != -1) {
186 0 : stats.codec_name = codec_inst.plname;
187 0 : stats.codec_payload_type = rtc::Optional<int>(codec_inst.pltype);
188 : }
189 0 : stats.ext_seqnum = call_stats.extendedMax;
190 0 : if (codec_inst.plfreq / 1000 > 0) {
191 0 : stats.jitter_ms = call_stats.jitterSamples / (codec_inst.plfreq / 1000);
192 : }
193 0 : stats.delay_estimate_ms = channel_proxy_->GetDelayEstimate();
194 0 : stats.audio_level = channel_proxy_->GetSpeechOutputLevelFullRange();
195 :
196 : // Get jitter buffer and total delay (alg + jitter + playout) stats.
197 0 : auto ns = channel_proxy_->GetNetworkStatistics();
198 0 : stats.jitter_buffer_ms = ns.currentBufferSize;
199 0 : stats.jitter_buffer_preferred_ms = ns.preferredBufferSize;
200 0 : stats.expand_rate = Q14ToFloat(ns.currentExpandRate);
201 0 : stats.speech_expand_rate = Q14ToFloat(ns.currentSpeechExpandRate);
202 0 : stats.secondary_decoded_rate = Q14ToFloat(ns.currentSecondaryDecodedRate);
203 0 : stats.accelerate_rate = Q14ToFloat(ns.currentAccelerateRate);
204 0 : stats.preemptive_expand_rate = Q14ToFloat(ns.currentPreemptiveRate);
205 :
206 0 : auto ds = channel_proxy_->GetDecodingCallStatistics();
207 0 : stats.decoding_calls_to_silence_generator = ds.calls_to_silence_generator;
208 0 : stats.decoding_calls_to_neteq = ds.calls_to_neteq;
209 0 : stats.decoding_normal = ds.decoded_normal;
210 0 : stats.decoding_plc = ds.decoded_plc;
211 0 : stats.decoding_cng = ds.decoded_cng;
212 0 : stats.decoding_plc_cng = ds.decoded_plc_cng;
213 0 : stats.decoding_muted_output = ds.decoded_muted_output;
214 :
215 0 : return stats;
216 : }
217 :
218 0 : void AudioReceiveStream::SetSink(std::unique_ptr<AudioSinkInterface> sink) {
219 0 : RTC_DCHECK_RUN_ON(&thread_checker_);
220 0 : channel_proxy_->SetSink(std::move(sink));
221 0 : }
222 :
223 0 : void AudioReceiveStream::SetGain(float gain) {
224 0 : RTC_DCHECK_RUN_ON(&thread_checker_);
225 0 : channel_proxy_->SetChannelOutputVolumeScaling(gain);
226 0 : }
227 :
228 0 : const webrtc::AudioReceiveStream::Config& AudioReceiveStream::config() const {
229 0 : RTC_DCHECK_RUN_ON(&thread_checker_);
230 0 : return config_;
231 : }
232 :
233 0 : void AudioReceiveStream::AssociateSendStream(AudioSendStream* send_stream) {
234 0 : RTC_DCHECK(thread_checker_.CalledOnValidThread());
235 0 : if (send_stream) {
236 0 : VoiceEngineImpl* voe_impl = static_cast<VoiceEngineImpl*>(voice_engine());
237 : std::unique_ptr<voe::ChannelProxy> send_channel_proxy =
238 0 : voe_impl->GetChannelProxy(send_stream->config().voe_channel_id);
239 0 : channel_proxy_->AssociateSendChannel(*send_channel_proxy.get());
240 : } else {
241 0 : channel_proxy_->DisassociateSendChannel();
242 : }
243 0 : }
244 :
245 0 : void AudioReceiveStream::SignalNetworkState(NetworkState state) {
246 0 : RTC_DCHECK_RUN_ON(&thread_checker_);
247 0 : }
248 :
249 0 : bool AudioReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) {
250 : // TODO(solenberg): Tests call this function on a network thread, libjingle
251 : // calls on the worker thread. We should move towards always using a network
252 : // thread. Then this check can be enabled.
253 : // RTC_DCHECK(!thread_checker_.CalledOnValidThread());
254 0 : return channel_proxy_->ReceivedRTCPPacket(packet, length);
255 : }
256 :
257 0 : bool AudioReceiveStream::DeliverRtp(const uint8_t* packet,
258 : size_t length,
259 : const PacketTime& packet_time) {
260 : // TODO(solenberg): Tests call this function on a network thread, libjingle
261 : // calls on the worker thread. We should move towards always using a network
262 : // thread. Then this check can be enabled.
263 : // RTC_DCHECK(!thread_checker_.CalledOnValidThread());
264 0 : RTPHeader header;
265 0 : if (!rtp_header_parser_->Parse(packet, length, &header)) {
266 0 : return false;
267 : }
268 :
269 : // Only forward if the parsed header has one of the headers necessary for
270 : // bandwidth estimation. RTP timestamps has different rates for audio and
271 : // video and shouldn't be mixed.
272 0 : if (config_.rtp.transport_cc &&
273 0 : header.extension.hasTransportSequenceNumber) {
274 0 : int64_t arrival_time_ms = rtc::TimeMillis();
275 0 : if (packet_time.timestamp >= 0)
276 0 : arrival_time_ms = (packet_time.timestamp + 500) / 1000;
277 0 : size_t payload_size = length - header.headerLength;
278 0 : remote_bitrate_estimator_->IncomingPacket(arrival_time_ms, payload_size,
279 0 : header);
280 : }
281 :
282 0 : return channel_proxy_->ReceivedRTPPacket(packet, length, packet_time);
283 : }
284 :
285 0 : AudioMixer::Source::AudioFrameInfo AudioReceiveStream::GetAudioFrameWithInfo(
286 : int sample_rate_hz,
287 : AudioFrame* audio_frame) {
288 0 : return channel_proxy_->GetAudioFrameWithInfo(sample_rate_hz, audio_frame);
289 : }
290 :
291 0 : int AudioReceiveStream::PreferredSampleRate() const {
292 0 : return channel_proxy_->NeededFrequency();
293 : }
294 :
295 0 : int AudioReceiveStream::Ssrc() const {
296 0 : return config_.rtp.remote_ssrc;
297 : }
298 :
299 0 : internal::AudioState* AudioReceiveStream::audio_state() const {
300 0 : auto* audio_state = static_cast<internal::AudioState*>(audio_state_.get());
301 0 : RTC_DCHECK(audio_state);
302 0 : return audio_state;
303 : }
304 :
305 0 : VoiceEngine* AudioReceiveStream::voice_engine() const {
306 0 : auto* voice_engine = audio_state()->voice_engine();
307 0 : RTC_DCHECK(voice_engine);
308 0 : return voice_engine;
309 : }
310 :
311 0 : int AudioReceiveStream::SetVoiceEnginePlayout(bool playout) {
312 0 : ScopedVoEInterface<VoEBase> base(voice_engine());
313 0 : if (playout) {
314 0 : return base->StartPlayout(config_.voe_channel_id);
315 : } else {
316 0 : return base->StopPlayout(config_.voe_channel_id);
317 : }
318 : }
319 :
320 : } // namespace internal
321 : } // namespace webrtc
|