blob: 87cb215bae6fa4473fd7588b85acfad4c124ae49 [file] [log] [blame]
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +02001/*
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
Peter Boström5c389d32015-09-25 13:58:30 +020011#include "webrtc/audio/audio_receive_stream.h"
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +020012
13#include <string>
14
solenberg566ef242015-11-06 15:34:49 -080015#include "webrtc/audio/audio_state.h"
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +020016#include "webrtc/audio/conversion.h"
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +020017#include "webrtc/base/checks.h"
pbosa2f30de2015-10-15 05:22:13 -070018#include "webrtc/base/logging.h"
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +020019#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010020#include "webrtc/system_wrappers/include/tick_util.h"
solenberg13725082015-11-25 08:16:52 -080021#include "webrtc/voice_engine/channel_proxy.h"
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +020022#include "webrtc/voice_engine/include/voe_base.h"
23#include "webrtc/voice_engine/include/voe_codec.h"
24#include "webrtc/voice_engine/include/voe_neteq_stats.h"
25#include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
26#include "webrtc/voice_engine/include/voe_video_sync.h"
27#include "webrtc/voice_engine/include/voe_volume_control.h"
solenberg13725082015-11-25 08:16:52 -080028#include "webrtc/voice_engine/voice_engine_impl.h"
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +020029
30namespace webrtc {
31std::string AudioReceiveStream::Config::Rtp::ToString() const {
32 std::stringstream ss;
33 ss << "{remote_ssrc: " << remote_ssrc;
solenberg85a04962015-10-27 03:35:21 -070034 ss << ", local_ssrc: " << local_ssrc;
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +020035 ss << ", extensions: [";
36 for (size_t i = 0; i < extensions.size(); ++i) {
37 ss << extensions[i].ToString();
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +020038 if (i != extensions.size() - 1) {
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +020039 ss << ", ";
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +020040 }
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +020041 }
42 ss << ']';
43 ss << '}';
44 return ss.str();
45}
46
47std::string AudioReceiveStream::Config::ToString() const {
48 std::stringstream ss;
49 ss << "{rtp: " << rtp.ToString();
solenberg85a04962015-10-27 03:35:21 -070050 ss << ", receive_transport: "
51 << (receive_transport ? "(Transport)" : "nullptr");
52 ss << ", rtcp_send_transport: "
53 << (rtcp_send_transport ? "(Transport)" : "nullptr");
pbos8fc7fa72015-07-15 08:02:58 -070054 ss << ", voe_channel_id: " << voe_channel_id;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +020055 if (!sync_group.empty()) {
pbos8fc7fa72015-07-15 08:02:58 -070056 ss << ", sync_group: " << sync_group;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +020057 }
solenberg85a04962015-10-27 03:35:21 -070058 ss << ", combined_audio_video_bwe: "
59 << (combined_audio_video_bwe ? "true" : "false");
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +020060 ss << '}';
61 return ss.str();
62}
63
64namespace internal {
65AudioReceiveStream::AudioReceiveStream(
solenberg566ef242015-11-06 15:34:49 -080066 RemoteBitrateEstimator* remote_bitrate_estimator,
67 const webrtc::AudioReceiveStream::Config& config,
68 const rtc::scoped_refptr<webrtc::AudioState>& audio_state)
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +020069 : remote_bitrate_estimator_(remote_bitrate_estimator),
70 config_(config),
solenberg566ef242015-11-06 15:34:49 -080071 audio_state_(audio_state),
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +020072 rtp_header_parser_(RtpHeaderParser::Create()) {
pbosa2f30de2015-10-15 05:22:13 -070073 LOG(LS_INFO) << "AudioReceiveStream: " << config_.ToString();
solenberg566ef242015-11-06 15:34:49 -080074 RTC_DCHECK_NE(config_.voe_channel_id, -1);
75 RTC_DCHECK(remote_bitrate_estimator_);
76 RTC_DCHECK(audio_state_.get());
77 RTC_DCHECK(rtp_header_parser_);
solenberg7add0582015-11-20 09:59:34 -080078
solenberg13725082015-11-25 08:16:52 -080079 VoiceEngineImpl* voe_impl = static_cast<VoiceEngineImpl*>(voice_engine());
80 channel_proxy_ = voe_impl->GetChannelProxy(config_.voe_channel_id);
81 channel_proxy_->SetLocalSSRC(config.rtp.local_ssrc);
solenberg7add0582015-11-20 09:59:34 -080082 for (const auto& extension : config.rtp.extensions) {
solenberg7add0582015-11-20 09:59:34 -080083 if (extension.name == RtpExtension::kAudioLevel) {
solenberg358057b2015-11-27 10:46:42 -080084 channel_proxy_->SetReceiveAudioLevelIndicationStatus(true, extension.id);
solenberg7add0582015-11-20 09:59:34 -080085 bool registered = rtp_header_parser_->RegisterRtpHeaderExtension(
86 kRtpExtensionAudioLevel, extension.id);
87 RTC_DCHECK(registered);
88 } else if (extension.name == RtpExtension::kAbsSendTime) {
solenberg358057b2015-11-27 10:46:42 -080089 channel_proxy_->SetReceiveAbsoluteSenderTimeStatus(true, extension.id);
solenberg7add0582015-11-20 09:59:34 -080090 bool registered = rtp_header_parser_->RegisterRtpHeaderExtension(
91 kRtpExtensionAbsoluteSendTime, extension.id);
92 RTC_DCHECK(registered);
93 } else if (extension.name == RtpExtension::kTransportSequenceNumber) {
94 // TODO(holmer): Need to do something here or in DeliverRtp() to actually
95 // handle audio packets with this header extension.
96 bool registered = rtp_header_parser_->RegisterRtpHeaderExtension(
97 kRtpExtensionTransportSequenceNumber, extension.id);
98 RTC_DCHECK(registered);
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +020099 } else {
100 RTC_NOTREACHED() << "Unsupported RTP extension.";
101 }
102 }
103}
104
pbosa2f30de2015-10-15 05:22:13 -0700105AudioReceiveStream::~AudioReceiveStream() {
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +0200106 RTC_DCHECK(thread_checker_.CalledOnValidThread());
pbosa2f30de2015-10-15 05:22:13 -0700107 LOG(LS_INFO) << "~AudioReceiveStream: " << config_.ToString();
108}
109
solenberg7add0582015-11-20 09:59:34 -0800110void AudioReceiveStream::Start() {
111 RTC_DCHECK(thread_checker_.CalledOnValidThread());
112}
113
114void AudioReceiveStream::Stop() {
115 RTC_DCHECK(thread_checker_.CalledOnValidThread());
116}
117
118void AudioReceiveStream::SignalNetworkState(NetworkState state) {
119 RTC_DCHECK(thread_checker_.CalledOnValidThread());
120}
121
122bool AudioReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) {
123 // TODO(solenberg): Tests call this function on a network thread, libjingle
124 // calls on the worker thread. We should move towards always using a network
125 // thread. Then this check can be enabled.
126 // RTC_DCHECK(!thread_checker_.CalledOnValidThread());
127 return false;
128}
129
130bool AudioReceiveStream::DeliverRtp(const uint8_t* packet,
131 size_t length,
132 const PacketTime& packet_time) {
133 // TODO(solenberg): Tests call this function on a network thread, libjingle
134 // calls on the worker thread. We should move towards always using a network
135 // thread. Then this check can be enabled.
136 // RTC_DCHECK(!thread_checker_.CalledOnValidThread());
137 RTPHeader header;
138 if (!rtp_header_parser_->Parse(packet, length, &header)) {
139 return false;
140 }
141
142 // Only forward if the parsed header has absolute sender time. RTP timestamps
143 // may have different rates for audio and video and shouldn't be mixed.
144 if (config_.combined_audio_video_bwe &&
145 header.extension.hasAbsoluteSendTime) {
146 int64_t arrival_time_ms = TickTime::MillisecondTimestamp();
147 if (packet_time.timestamp >= 0)
148 arrival_time_ms = (packet_time.timestamp + 500) / 1000;
149 size_t payload_size = length - header.headerLength;
150 remote_bitrate_estimator_->IncomingPacket(arrival_time_ms, payload_size,
151 header, false);
152 }
153 return true;
154}
155
Fredrik Solenberg04f49312015-06-08 13:04:56 +0200156webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +0200157 RTC_DCHECK(thread_checker_.CalledOnValidThread());
158 webrtc::AudioReceiveStream::Stats stats;
159 stats.remote_ssrc = config_.rtp.remote_ssrc;
solenberg7add0582015-11-20 09:59:34 -0800160 ScopedVoEInterface<VoECodec> codec(voice_engine());
solenberg8b85de22015-11-16 09:48:04 -0800161
solenberg358057b2015-11-27 10:46:42 -0800162 webrtc::CallStatistics call_stats = channel_proxy_->GetRTCPStatistics();
solenberg85a04962015-10-27 03:35:21 -0700163 webrtc::CodecInst codec_inst = {0};
solenberg8b85de22015-11-16 09:48:04 -0800164 if (codec->GetRecCodec(config_.voe_channel_id, codec_inst) == -1) {
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +0200165 return stats;
166 }
167
solenberg85a04962015-10-27 03:35:21 -0700168 stats.bytes_rcvd = call_stats.bytesReceived;
169 stats.packets_rcvd = call_stats.packetsReceived;
170 stats.packets_lost = call_stats.cumulativeLost;
171 stats.fraction_lost = Q8ToFloat(call_stats.fractionLost);
solenberg8b85de22015-11-16 09:48:04 -0800172 stats.capture_start_ntp_time_ms = call_stats.capture_start_ntp_time_ms_;
solenberg85a04962015-10-27 03:35:21 -0700173 if (codec_inst.pltype != -1) {
174 stats.codec_name = codec_inst.plname;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +0200175 }
solenberg85a04962015-10-27 03:35:21 -0700176 stats.ext_seqnum = call_stats.extendedMax;
177 if (codec_inst.plfreq / 1000 > 0) {
178 stats.jitter_ms = call_stats.jitterSamples / (codec_inst.plfreq / 1000);
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +0200179 }
solenberg358057b2015-11-27 10:46:42 -0800180 stats.delay_estimate_ms = channel_proxy_->GetDelayEstimate();
181 stats.audio_level = channel_proxy_->GetSpeechOutputLevelFullRange();
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +0200182
solenberg8b85de22015-11-16 09:48:04 -0800183 // Get jitter buffer and total delay (alg + jitter + playout) stats.
solenberg358057b2015-11-27 10:46:42 -0800184 auto ns = channel_proxy_->GetNetworkStatistics();
solenberg8b85de22015-11-16 09:48:04 -0800185 stats.jitter_buffer_ms = ns.currentBufferSize;
186 stats.jitter_buffer_preferred_ms = ns.preferredBufferSize;
187 stats.expand_rate = Q14ToFloat(ns.currentExpandRate);
188 stats.speech_expand_rate = Q14ToFloat(ns.currentSpeechExpandRate);
189 stats.secondary_decoded_rate = Q14ToFloat(ns.currentSecondaryDecodedRate);
190 stats.accelerate_rate = Q14ToFloat(ns.currentAccelerateRate);
191 stats.preemptive_expand_rate = Q14ToFloat(ns.currentPreemptiveRate);
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +0200192
solenberg358057b2015-11-27 10:46:42 -0800193 auto ds = channel_proxy_->GetDecodingCallStatistics();
solenberg8b85de22015-11-16 09:48:04 -0800194 stats.decoding_calls_to_silence_generator = ds.calls_to_silence_generator;
195 stats.decoding_calls_to_neteq = ds.calls_to_neteq;
196 stats.decoding_normal = ds.decoded_normal;
197 stats.decoding_plc = ds.decoded_plc;
198 stats.decoding_cng = ds.decoded_cng;
199 stats.decoding_plc_cng = ds.decoded_plc_cng;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +0200200
201 return stats;
Fredrik Solenberg04f49312015-06-08 13:04:56 +0200202}
203
pbosa2f30de2015-10-15 05:22:13 -0700204const webrtc::AudioReceiveStream::Config& AudioReceiveStream::config() const {
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +0200205 RTC_DCHECK(thread_checker_.CalledOnValidThread());
pbosa2f30de2015-10-15 05:22:13 -0700206 return config_;
207}
208
solenberg7add0582015-11-20 09:59:34 -0800209VoiceEngine* AudioReceiveStream::voice_engine() const {
210 internal::AudioState* audio_state =
211 static_cast<internal::AudioState*>(audio_state_.get());
212 VoiceEngine* voice_engine = audio_state->voice_engine();
213 RTC_DCHECK(voice_engine);
214 return voice_engine;
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +0200215}
216} // namespace internal
217} // namespace webrtc