123fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg/*
223fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
323fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg *
423fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg *  Use of this source code is governed by a BSD-style license
523fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg *  that can be found in the LICENSE file in the root of the source
623fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg *  tree. An additional intellectual property rights grant can be found
723fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg *  in the file PATENTS.  All contributing project authors may
823fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg *  be found in the AUTHORS file in the root of the source tree.
923fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg */
1023fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg
115c389d3e09646c0e2ed76d5ccb37a3419a09eb6aPeter Boström#include "webrtc/audio/audio_receive_stream.h"
1223fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg
1323fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg#include <string>
14f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi#include <utility>
1523fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg
16f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi#include "webrtc/audio/audio_sink.h"
17566ef247b9779f6c9d0e7ec9eea6b037f4682c53solenberg#include "webrtc/audio/audio_state.h"
184f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg#include "webrtc/audio/conversion.h"
1923fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg#include "webrtc/base/checks.h"
20a2f30deea342896ee40cc4d90567f091efbe0fc9pbos#include "webrtc/base/logging.h"
213842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer#include "webrtc/call/congestion_controller.h"
2223fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
2398f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/tick_util.h"
2413725089ef91f932b37b2447c3f05d9cd9f89984solenberg#include "webrtc/voice_engine/channel_proxy.h"
254f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg#include "webrtc/voice_engine/include/voe_base.h"
264f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg#include "webrtc/voice_engine/include/voe_codec.h"
274f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg#include "webrtc/voice_engine/include/voe_neteq_stats.h"
284f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg#include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
294f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg#include "webrtc/voice_engine/include/voe_video_sync.h"
304f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg#include "webrtc/voice_engine/include/voe_volume_control.h"
3113725089ef91f932b37b2447c3f05d9cd9f89984solenberg#include "webrtc/voice_engine/voice_engine_impl.h"
3223fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg
3323fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenbergnamespace webrtc {
343842c5c7f73639527e653f41c65334245d2317a1Stefan Holmernamespace {
353842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer
363842c5c7f73639527e653f41c65334245d2317a1Stefan Holmerbool UseSendSideBwe(const webrtc::AudioReceiveStream::Config& config) {
373842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer  if (!config.rtp.transport_cc) {
383842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer    return false;
393842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer  }
403842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer  for (const auto& extension : config.rtp.extensions) {
413842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer    if (extension.name == RtpExtension::kTransportSequenceNumber) {
423842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer      return true;
433842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer    }
443842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer  }
453842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer  return false;
463842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer}
473842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer}  // namespace
483842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer
4923fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenbergstd::string AudioReceiveStream::Config::Rtp::ToString() const {
5023fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg  std::stringstream ss;
5123fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg  ss << "{remote_ssrc: " << remote_ssrc;
5285a0496b8c4ac01da7c716ea7950093659864c8esolenberg  ss << ", local_ssrc: " << local_ssrc;
5323fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg  ss << ", extensions: [";
5423fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg  for (size_t i = 0; i < extensions.size(); ++i) {
5523fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg    ss << extensions[i].ToString();
564f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg    if (i != extensions.size() - 1) {
5723fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg      ss << ", ";
584f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg    }
5923fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg  }
6023fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg  ss << ']';
6123fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg  ss << '}';
6223fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg  return ss.str();
6323fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg}
6423fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg
6523fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenbergstd::string AudioReceiveStream::Config::ToString() const {
6623fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg  std::stringstream ss;
6723fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg  ss << "{rtp: " << rtp.ToString();
6885a0496b8c4ac01da7c716ea7950093659864c8esolenberg  ss << ", receive_transport: "
6985a0496b8c4ac01da7c716ea7950093659864c8esolenberg     << (receive_transport ? "(Transport)" : "nullptr");
7085a0496b8c4ac01da7c716ea7950093659864c8esolenberg  ss << ", rtcp_send_transport: "
7185a0496b8c4ac01da7c716ea7950093659864c8esolenberg     << (rtcp_send_transport ? "(Transport)" : "nullptr");
728fc7fa798f7a36955f1b933980401afad2aff592pbos  ss << ", voe_channel_id: " << voe_channel_id;
734f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg  if (!sync_group.empty()) {
748fc7fa798f7a36955f1b933980401afad2aff592pbos    ss << ", sync_group: " << sync_group;
754f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg  }
7685a0496b8c4ac01da7c716ea7950093659864c8esolenberg  ss << ", combined_audio_video_bwe: "
7785a0496b8c4ac01da7c716ea7950093659864c8esolenberg     << (combined_audio_video_bwe ? "true" : "false");
7823fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg  ss << '}';
7923fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg  return ss.str();
8023fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg}
8123fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg
8223fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenbergnamespace internal {
8323fba1ffa0079f70744a83bcf4e85501dc226013Fredrik SolenbergAudioReceiveStream::AudioReceiveStream(
843842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer    CongestionController* congestion_controller,
85566ef247b9779f6c9d0e7ec9eea6b037f4682c53solenberg    const webrtc::AudioReceiveStream::Config& config,
86566ef247b9779f6c9d0e7ec9eea6b037f4682c53solenberg    const rtc::scoped_refptr<webrtc::AudioState>& audio_state)
873842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer    : config_(config),
88566ef247b9779f6c9d0e7ec9eea6b037f4682c53solenberg      audio_state_(audio_state),
8923fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg      rtp_header_parser_(RtpHeaderParser::Create()) {
90a2f30deea342896ee40cc4d90567f091efbe0fc9pbos  LOG(LS_INFO) << "AudioReceiveStream: " << config_.ToString();
91566ef247b9779f6c9d0e7ec9eea6b037f4682c53solenberg  RTC_DCHECK_NE(config_.voe_channel_id, -1);
92566ef247b9779f6c9d0e7ec9eea6b037f4682c53solenberg  RTC_DCHECK(audio_state_.get());
933842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer  RTC_DCHECK(congestion_controller);
94566ef247b9779f6c9d0e7ec9eea6b037f4682c53solenberg  RTC_DCHECK(rtp_header_parser_);
957add0584390dcfb236165a6472ede6c2a94eaeedsolenberg
9613725089ef91f932b37b2447c3f05d9cd9f89984solenberg  VoiceEngineImpl* voe_impl = static_cast<VoiceEngineImpl*>(voice_engine());
9713725089ef91f932b37b2447c3f05d9cd9f89984solenberg  channel_proxy_ = voe_impl->GetChannelProxy(config_.voe_channel_id);
9813725089ef91f932b37b2447c3f05d9cd9f89984solenberg  channel_proxy_->SetLocalSSRC(config.rtp.local_ssrc);
997add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  for (const auto& extension : config.rtp.extensions) {
1007add0584390dcfb236165a6472ede6c2a94eaeedsolenberg    if (extension.name == RtpExtension::kAudioLevel) {
101358057b945725390bcecc330513160aa823f651esolenberg      channel_proxy_->SetReceiveAudioLevelIndicationStatus(true, extension.id);
1027add0584390dcfb236165a6472ede6c2a94eaeedsolenberg      bool registered = rtp_header_parser_->RegisterRtpHeaderExtension(
1037add0584390dcfb236165a6472ede6c2a94eaeedsolenberg          kRtpExtensionAudioLevel, extension.id);
1047add0584390dcfb236165a6472ede6c2a94eaeedsolenberg      RTC_DCHECK(registered);
1057add0584390dcfb236165a6472ede6c2a94eaeedsolenberg    } else if (extension.name == RtpExtension::kAbsSendTime) {
106358057b945725390bcecc330513160aa823f651esolenberg      channel_proxy_->SetReceiveAbsoluteSenderTimeStatus(true, extension.id);
1077add0584390dcfb236165a6472ede6c2a94eaeedsolenberg      bool registered = rtp_header_parser_->RegisterRtpHeaderExtension(
1087add0584390dcfb236165a6472ede6c2a94eaeedsolenberg          kRtpExtensionAbsoluteSendTime, extension.id);
1097add0584390dcfb236165a6472ede6c2a94eaeedsolenberg      RTC_DCHECK(registered);
1107add0584390dcfb236165a6472ede6c2a94eaeedsolenberg    } else if (extension.name == RtpExtension::kTransportSequenceNumber) {
1117add0584390dcfb236165a6472ede6c2a94eaeedsolenberg      bool registered = rtp_header_parser_->RegisterRtpHeaderExtension(
1127add0584390dcfb236165a6472ede6c2a94eaeedsolenberg          kRtpExtensionTransportSequenceNumber, extension.id);
1137add0584390dcfb236165a6472ede6c2a94eaeedsolenberg      RTC_DCHECK(registered);
11423fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg    } else {
11523fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg      RTC_NOTREACHED() << "Unsupported RTP extension.";
11623fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg    }
11723fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg  }
1183842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer  // Configure bandwidth estimation.
1193842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer  channel_proxy_->SetCongestionControlObjects(
1203842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer      nullptr, nullptr, congestion_controller->packet_router());
1213842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer  if (config.combined_audio_video_bwe) {
1223842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer    if (UseSendSideBwe(config)) {
1233842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer      remote_bitrate_estimator_ =
1243842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer          congestion_controller->GetRemoteBitrateEstimator(true);
1253842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer    } else {
1263842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer      remote_bitrate_estimator_ =
1273842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer          congestion_controller->GetRemoteBitrateEstimator(false);
1283842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer    }
1293842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer    RTC_DCHECK(remote_bitrate_estimator_);
1303842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer  }
13123fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg}
13223fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg
133a2f30deea342896ee40cc4d90567f091efbe0fc9pbosAudioReceiveStream::~AudioReceiveStream() {
1344f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg  RTC_DCHECK(thread_checker_.CalledOnValidThread());
135a2f30deea342896ee40cc4d90567f091efbe0fc9pbos  LOG(LS_INFO) << "~AudioReceiveStream: " << config_.ToString();
1363842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer  channel_proxy_->SetCongestionControlObjects(nullptr, nullptr, nullptr);
1373842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer  if (remote_bitrate_estimator_) {
1383842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer    remote_bitrate_estimator_->RemoveStream(config_.rtp.remote_ssrc);
1393842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer  }
140a2f30deea342896ee40cc4d90567f091efbe0fc9pbos}
141a2f30deea342896ee40cc4d90567f091efbe0fc9pbos
1427add0584390dcfb236165a6472ede6c2a94eaeedsolenbergvoid AudioReceiveStream::Start() {
1437add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  RTC_DCHECK(thread_checker_.CalledOnValidThread());
1447add0584390dcfb236165a6472ede6c2a94eaeedsolenberg}
1457add0584390dcfb236165a6472ede6c2a94eaeedsolenberg
1467add0584390dcfb236165a6472ede6c2a94eaeedsolenbergvoid AudioReceiveStream::Stop() {
1477add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  RTC_DCHECK(thread_checker_.CalledOnValidThread());
1487add0584390dcfb236165a6472ede6c2a94eaeedsolenberg}
1497add0584390dcfb236165a6472ede6c2a94eaeedsolenberg
1507add0584390dcfb236165a6472ede6c2a94eaeedsolenbergvoid AudioReceiveStream::SignalNetworkState(NetworkState state) {
1517add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  RTC_DCHECK(thread_checker_.CalledOnValidThread());
1527add0584390dcfb236165a6472ede6c2a94eaeedsolenberg}
1537add0584390dcfb236165a6472ede6c2a94eaeedsolenberg
1547add0584390dcfb236165a6472ede6c2a94eaeedsolenbergbool AudioReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) {
1557add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  // TODO(solenberg): Tests call this function on a network thread, libjingle
1567add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  // calls on the worker thread. We should move towards always using a network
1577add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  // thread. Then this check can be enabled.
1587add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  // RTC_DCHECK(!thread_checker_.CalledOnValidThread());
1597add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  return false;
1607add0584390dcfb236165a6472ede6c2a94eaeedsolenberg}
1617add0584390dcfb236165a6472ede6c2a94eaeedsolenberg
1627add0584390dcfb236165a6472ede6c2a94eaeedsolenbergbool AudioReceiveStream::DeliverRtp(const uint8_t* packet,
1637add0584390dcfb236165a6472ede6c2a94eaeedsolenberg                                    size_t length,
1647add0584390dcfb236165a6472ede6c2a94eaeedsolenberg                                    const PacketTime& packet_time) {
1657add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  // TODO(solenberg): Tests call this function on a network thread, libjingle
1667add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  // calls on the worker thread. We should move towards always using a network
1677add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  // thread. Then this check can be enabled.
1687add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  // RTC_DCHECK(!thread_checker_.CalledOnValidThread());
1697add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  RTPHeader header;
1707add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  if (!rtp_header_parser_->Parse(packet, length, &header)) {
1717add0584390dcfb236165a6472ede6c2a94eaeedsolenberg    return false;
1727add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  }
1737add0584390dcfb236165a6472ede6c2a94eaeedsolenberg
1743842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer  // Only forward if the parsed header has one of the headers necessary for
1753842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer  // bandwidth estimation. RTP timestamps has different rates for audio and
1763842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer  // video and shouldn't be mixed.
1773842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer  if (remote_bitrate_estimator_ &&
1783842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer      (header.extension.hasAbsoluteSendTime ||
1793842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer       header.extension.hasTransportSequenceNumber)) {
1807add0584390dcfb236165a6472ede6c2a94eaeedsolenberg    int64_t arrival_time_ms = TickTime::MillisecondTimestamp();
1817add0584390dcfb236165a6472ede6c2a94eaeedsolenberg    if (packet_time.timestamp >= 0)
1827add0584390dcfb236165a6472ede6c2a94eaeedsolenberg      arrival_time_ms = (packet_time.timestamp + 500) / 1000;
1837add0584390dcfb236165a6472ede6c2a94eaeedsolenberg    size_t payload_size = length - header.headerLength;
1847add0584390dcfb236165a6472ede6c2a94eaeedsolenberg    remote_bitrate_estimator_->IncomingPacket(arrival_time_ms, payload_size,
1857add0584390dcfb236165a6472ede6c2a94eaeedsolenberg                                              header, false);
1867add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  }
1877add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  return true;
1887add0584390dcfb236165a6472ede6c2a94eaeedsolenberg}
1897add0584390dcfb236165a6472ede6c2a94eaeedsolenberg
19004f4931ef06273c2873e7816ed1f568d445117b8Fredrik Solenbergwebrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
1914f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg  RTC_DCHECK(thread_checker_.CalledOnValidThread());
1924f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg  webrtc::AudioReceiveStream::Stats stats;
1934f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg  stats.remote_ssrc = config_.rtp.remote_ssrc;
1947add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  ScopedVoEInterface<VoECodec> codec(voice_engine());
195358057b945725390bcecc330513160aa823f651esolenberg
196358057b945725390bcecc330513160aa823f651esolenberg  webrtc::CallStatistics call_stats = channel_proxy_->GetRTCPStatistics();
19785a0496b8c4ac01da7c716ea7950093659864c8esolenberg  webrtc::CodecInst codec_inst = {0};
1988b85de2ba1a8885b70bf9fe8beadc54c5c405335solenberg  if (codec->GetRecCodec(config_.voe_channel_id, codec_inst) == -1) {
1994f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg    return stats;
2004f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg  }
2014f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg
20285a0496b8c4ac01da7c716ea7950093659864c8esolenberg  stats.bytes_rcvd = call_stats.bytesReceived;
20385a0496b8c4ac01da7c716ea7950093659864c8esolenberg  stats.packets_rcvd = call_stats.packetsReceived;
20485a0496b8c4ac01da7c716ea7950093659864c8esolenberg  stats.packets_lost = call_stats.cumulativeLost;
20585a0496b8c4ac01da7c716ea7950093659864c8esolenberg  stats.fraction_lost = Q8ToFloat(call_stats.fractionLost);
2068b85de2ba1a8885b70bf9fe8beadc54c5c405335solenberg  stats.capture_start_ntp_time_ms = call_stats.capture_start_ntp_time_ms_;
20785a0496b8c4ac01da7c716ea7950093659864c8esolenberg  if (codec_inst.pltype != -1) {
20885a0496b8c4ac01da7c716ea7950093659864c8esolenberg    stats.codec_name = codec_inst.plname;
2094f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg  }
21085a0496b8c4ac01da7c716ea7950093659864c8esolenberg  stats.ext_seqnum = call_stats.extendedMax;
21185a0496b8c4ac01da7c716ea7950093659864c8esolenberg  if (codec_inst.plfreq / 1000 > 0) {
21285a0496b8c4ac01da7c716ea7950093659864c8esolenberg    stats.jitter_ms = call_stats.jitterSamples / (codec_inst.plfreq / 1000);
2134f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg  }
214358057b945725390bcecc330513160aa823f651esolenberg  stats.delay_estimate_ms = channel_proxy_->GetDelayEstimate();
215358057b945725390bcecc330513160aa823f651esolenberg  stats.audio_level = channel_proxy_->GetSpeechOutputLevelFullRange();
2164f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg
2178b85de2ba1a8885b70bf9fe8beadc54c5c405335solenberg  // Get jitter buffer and total delay (alg + jitter + playout) stats.
218358057b945725390bcecc330513160aa823f651esolenberg  auto ns = channel_proxy_->GetNetworkStatistics();
2198b85de2ba1a8885b70bf9fe8beadc54c5c405335solenberg  stats.jitter_buffer_ms = ns.currentBufferSize;
2208b85de2ba1a8885b70bf9fe8beadc54c5c405335solenberg  stats.jitter_buffer_preferred_ms = ns.preferredBufferSize;
2218b85de2ba1a8885b70bf9fe8beadc54c5c405335solenberg  stats.expand_rate = Q14ToFloat(ns.currentExpandRate);
2228b85de2ba1a8885b70bf9fe8beadc54c5c405335solenberg  stats.speech_expand_rate = Q14ToFloat(ns.currentSpeechExpandRate);
2238b85de2ba1a8885b70bf9fe8beadc54c5c405335solenberg  stats.secondary_decoded_rate = Q14ToFloat(ns.currentSecondaryDecodedRate);
2248b85de2ba1a8885b70bf9fe8beadc54c5c405335solenberg  stats.accelerate_rate = Q14ToFloat(ns.currentAccelerateRate);
2258b85de2ba1a8885b70bf9fe8beadc54c5c405335solenberg  stats.preemptive_expand_rate = Q14ToFloat(ns.currentPreemptiveRate);
2264f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg
227358057b945725390bcecc330513160aa823f651esolenberg  auto ds = channel_proxy_->GetDecodingCallStatistics();
2288b85de2ba1a8885b70bf9fe8beadc54c5c405335solenberg  stats.decoding_calls_to_silence_generator = ds.calls_to_silence_generator;
2298b85de2ba1a8885b70bf9fe8beadc54c5c405335solenberg  stats.decoding_calls_to_neteq = ds.calls_to_neteq;
2308b85de2ba1a8885b70bf9fe8beadc54c5c405335solenberg  stats.decoding_normal = ds.decoded_normal;
2318b85de2ba1a8885b70bf9fe8beadc54c5c405335solenberg  stats.decoding_plc = ds.decoded_plc;
2328b85de2ba1a8885b70bf9fe8beadc54c5c405335solenberg  stats.decoding_cng = ds.decoded_cng;
2338b85de2ba1a8885b70bf9fe8beadc54c5c405335solenberg  stats.decoding_plc_cng = ds.decoded_plc_cng;
2344f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg
2354f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg  return stats;
23604f4931ef06273c2873e7816ed1f568d445117b8Fredrik Solenberg}
23704f4931ef06273c2873e7816ed1f568d445117b8Fredrik Solenberg
2382d110be77f14cab0bb51efe8b61d9c7a967d04cbdeadbeefvoid AudioReceiveStream::SetSink(rtc::scoped_ptr<AudioSinkInterface> sink) {
239f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi  RTC_DCHECK(thread_checker_.CalledOnValidThread());
2402d110be77f14cab0bb51efe8b61d9c7a967d04cbdeadbeef  channel_proxy_->SetSink(std::move(sink));
241f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi}
242f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi
243a2f30deea342896ee40cc4d90567f091efbe0fc9pbosconst webrtc::AudioReceiveStream::Config& AudioReceiveStream::config() const {
2444f4ec0a9270a8cefadfa12e9fa3b979b58b15392Fredrik Solenberg  RTC_DCHECK(thread_checker_.CalledOnValidThread());
245a2f30deea342896ee40cc4d90567f091efbe0fc9pbos  return config_;
246a2f30deea342896ee40cc4d90567f091efbe0fc9pbos}
247a2f30deea342896ee40cc4d90567f091efbe0fc9pbos
2487add0584390dcfb236165a6472ede6c2a94eaeedsolenbergVoiceEngine* AudioReceiveStream::voice_engine() const {
2497add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  internal::AudioState* audio_state =
2507add0584390dcfb236165a6472ede6c2a94eaeedsolenberg      static_cast<internal::AudioState*>(audio_state_.get());
2517add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  VoiceEngine* voice_engine = audio_state->voice_engine();
2527add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  RTC_DCHECK(voice_engine);
2537add0584390dcfb236165a6472ede6c2a94eaeedsolenberg  return voice_engine;
25423fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg}
25523fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg}  // namespace internal
25623fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg}  // namespace webrtc
257