Home | History | Annotate | Download | only in audio
      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/audio/audio_sink.h"
     17 #include "webrtc/audio/audio_state.h"
     18 #include "webrtc/audio/conversion.h"
     19 #include "webrtc/base/checks.h"
     20 #include "webrtc/base/logging.h"
     21 #include "webrtc/call/congestion_controller.h"
     22 #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
     23 #include "webrtc/system_wrappers/include/tick_util.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 namespace {
     35 
     36 bool UseSendSideBwe(const webrtc::AudioReceiveStream::Config& config) {
     37   if (!config.rtp.transport_cc) {
     38     return false;
     39   }
     40   for (const auto& extension : config.rtp.extensions) {
     41     if (extension.name == RtpExtension::kTransportSequenceNumber) {
     42       return true;
     43     }
     44   }
     45   return false;
     46 }
     47 }  // namespace
     48 
     49 std::string AudioReceiveStream::Config::Rtp::ToString() const {
     50   std::stringstream ss;
     51   ss << "{remote_ssrc: " << remote_ssrc;
     52   ss << ", local_ssrc: " << local_ssrc;
     53   ss << ", extensions: [";
     54   for (size_t i = 0; i < extensions.size(); ++i) {
     55     ss << extensions[i].ToString();
     56     if (i != extensions.size() - 1) {
     57       ss << ", ";
     58     }
     59   }
     60   ss << ']';
     61   ss << '}';
     62   return ss.str();
     63 }
     64 
     65 std::string AudioReceiveStream::Config::ToString() const {
     66   std::stringstream ss;
     67   ss << "{rtp: " << rtp.ToString();
     68   ss << ", receive_transport: "
     69      << (receive_transport ? "(Transport)" : "nullptr");
     70   ss << ", rtcp_send_transport: "
     71      << (rtcp_send_transport ? "(Transport)" : "nullptr");
     72   ss << ", voe_channel_id: " << voe_channel_id;
     73   if (!sync_group.empty()) {
     74     ss << ", sync_group: " << sync_group;
     75   }
     76   ss << ", combined_audio_video_bwe: "
     77      << (combined_audio_video_bwe ? "true" : "false");
     78   ss << '}';
     79   return ss.str();
     80 }
     81 
     82 namespace internal {
     83 AudioReceiveStream::AudioReceiveStream(
     84     CongestionController* congestion_controller,
     85     const webrtc::AudioReceiveStream::Config& config,
     86     const rtc::scoped_refptr<webrtc::AudioState>& audio_state)
     87     : config_(config),
     88       audio_state_(audio_state),
     89       rtp_header_parser_(RtpHeaderParser::Create()) {
     90   LOG(LS_INFO) << "AudioReceiveStream: " << config_.ToString();
     91   RTC_DCHECK_NE(config_.voe_channel_id, -1);
     92   RTC_DCHECK(audio_state_.get());
     93   RTC_DCHECK(congestion_controller);
     94   RTC_DCHECK(rtp_header_parser_);
     95 
     96   VoiceEngineImpl* voe_impl = static_cast<VoiceEngineImpl*>(voice_engine());
     97   channel_proxy_ = voe_impl->GetChannelProxy(config_.voe_channel_id);
     98   channel_proxy_->SetLocalSSRC(config.rtp.local_ssrc);
     99   for (const auto& extension : config.rtp.extensions) {
    100     if (extension.name == RtpExtension::kAudioLevel) {
    101       channel_proxy_->SetReceiveAudioLevelIndicationStatus(true, extension.id);
    102       bool registered = rtp_header_parser_->RegisterRtpHeaderExtension(
    103           kRtpExtensionAudioLevel, extension.id);
    104       RTC_DCHECK(registered);
    105     } else if (extension.name == RtpExtension::kAbsSendTime) {
    106       channel_proxy_->SetReceiveAbsoluteSenderTimeStatus(true, extension.id);
    107       bool registered = rtp_header_parser_->RegisterRtpHeaderExtension(
    108           kRtpExtensionAbsoluteSendTime, extension.id);
    109       RTC_DCHECK(registered);
    110     } else if (extension.name == RtpExtension::kTransportSequenceNumber) {
    111       bool registered = rtp_header_parser_->RegisterRtpHeaderExtension(
    112           kRtpExtensionTransportSequenceNumber, extension.id);
    113       RTC_DCHECK(registered);
    114     } else {
    115       RTC_NOTREACHED() << "Unsupported RTP extension.";
    116     }
    117   }
    118   // Configure bandwidth estimation.
    119   channel_proxy_->SetCongestionControlObjects(
    120       nullptr, nullptr, congestion_controller->packet_router());
    121   if (config.combined_audio_video_bwe) {
    122     if (UseSendSideBwe(config)) {
    123       remote_bitrate_estimator_ =
    124           congestion_controller->GetRemoteBitrateEstimator(true);
    125     } else {
    126       remote_bitrate_estimator_ =
    127           congestion_controller->GetRemoteBitrateEstimator(false);
    128     }
    129     RTC_DCHECK(remote_bitrate_estimator_);
    130   }
    131 }
    132 
    133 AudioReceiveStream::~AudioReceiveStream() {
    134   RTC_DCHECK(thread_checker_.CalledOnValidThread());
    135   LOG(LS_INFO) << "~AudioReceiveStream: " << config_.ToString();
    136   channel_proxy_->SetCongestionControlObjects(nullptr, nullptr, nullptr);
    137   if (remote_bitrate_estimator_) {
    138     remote_bitrate_estimator_->RemoveStream(config_.rtp.remote_ssrc);
    139   }
    140 }
    141 
    142 void AudioReceiveStream::Start() {
    143   RTC_DCHECK(thread_checker_.CalledOnValidThread());
    144 }
    145 
    146 void AudioReceiveStream::Stop() {
    147   RTC_DCHECK(thread_checker_.CalledOnValidThread());
    148 }
    149 
    150 void AudioReceiveStream::SignalNetworkState(NetworkState state) {
    151   RTC_DCHECK(thread_checker_.CalledOnValidThread());
    152 }
    153 
    154 bool AudioReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) {
    155   // TODO(solenberg): Tests call this function on a network thread, libjingle
    156   // calls on the worker thread. We should move towards always using a network
    157   // thread. Then this check can be enabled.
    158   // RTC_DCHECK(!thread_checker_.CalledOnValidThread());
    159   return false;
    160 }
    161 
    162 bool AudioReceiveStream::DeliverRtp(const uint8_t* packet,
    163                                     size_t length,
    164                                     const PacketTime& packet_time) {
    165   // TODO(solenberg): Tests call this function on a network thread, libjingle
    166   // calls on the worker thread. We should move towards always using a network
    167   // thread. Then this check can be enabled.
    168   // RTC_DCHECK(!thread_checker_.CalledOnValidThread());
    169   RTPHeader header;
    170   if (!rtp_header_parser_->Parse(packet, length, &header)) {
    171     return false;
    172   }
    173 
    174   // Only forward if the parsed header has one of the headers necessary for
    175   // bandwidth estimation. RTP timestamps has different rates for audio and
    176   // video and shouldn't be mixed.
    177   if (remote_bitrate_estimator_ &&
    178       (header.extension.hasAbsoluteSendTime ||
    179        header.extension.hasTransportSequenceNumber)) {
    180     int64_t arrival_time_ms = TickTime::MillisecondTimestamp();
    181     if (packet_time.timestamp >= 0)
    182       arrival_time_ms = (packet_time.timestamp + 500) / 1000;
    183     size_t payload_size = length - header.headerLength;
    184     remote_bitrate_estimator_->IncomingPacket(arrival_time_ms, payload_size,
    185                                               header, false);
    186   }
    187   return true;
    188 }
    189 
    190 webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
    191   RTC_DCHECK(thread_checker_.CalledOnValidThread());
    192   webrtc::AudioReceiveStream::Stats stats;
    193   stats.remote_ssrc = config_.rtp.remote_ssrc;
    194   ScopedVoEInterface<VoECodec> codec(voice_engine());
    195 
    196   webrtc::CallStatistics call_stats = channel_proxy_->GetRTCPStatistics();
    197   webrtc::CodecInst codec_inst = {0};
    198   if (codec->GetRecCodec(config_.voe_channel_id, codec_inst) == -1) {
    199     return stats;
    200   }
    201 
    202   stats.bytes_rcvd = call_stats.bytesReceived;
    203   stats.packets_rcvd = call_stats.packetsReceived;
    204   stats.packets_lost = call_stats.cumulativeLost;
    205   stats.fraction_lost = Q8ToFloat(call_stats.fractionLost);
    206   stats.capture_start_ntp_time_ms = call_stats.capture_start_ntp_time_ms_;
    207   if (codec_inst.pltype != -1) {
    208     stats.codec_name = codec_inst.plname;
    209   }
    210   stats.ext_seqnum = call_stats.extendedMax;
    211   if (codec_inst.plfreq / 1000 > 0) {
    212     stats.jitter_ms = call_stats.jitterSamples / (codec_inst.plfreq / 1000);
    213   }
    214   stats.delay_estimate_ms = channel_proxy_->GetDelayEstimate();
    215   stats.audio_level = channel_proxy_->GetSpeechOutputLevelFullRange();
    216 
    217   // Get jitter buffer and total delay (alg + jitter + playout) stats.
    218   auto ns = channel_proxy_->GetNetworkStatistics();
    219   stats.jitter_buffer_ms = ns.currentBufferSize;
    220   stats.jitter_buffer_preferred_ms = ns.preferredBufferSize;
    221   stats.expand_rate = Q14ToFloat(ns.currentExpandRate);
    222   stats.speech_expand_rate = Q14ToFloat(ns.currentSpeechExpandRate);
    223   stats.secondary_decoded_rate = Q14ToFloat(ns.currentSecondaryDecodedRate);
    224   stats.accelerate_rate = Q14ToFloat(ns.currentAccelerateRate);
    225   stats.preemptive_expand_rate = Q14ToFloat(ns.currentPreemptiveRate);
    226 
    227   auto ds = channel_proxy_->GetDecodingCallStatistics();
    228   stats.decoding_calls_to_silence_generator = ds.calls_to_silence_generator;
    229   stats.decoding_calls_to_neteq = ds.calls_to_neteq;
    230   stats.decoding_normal = ds.decoded_normal;
    231   stats.decoding_plc = ds.decoded_plc;
    232   stats.decoding_cng = ds.decoded_cng;
    233   stats.decoding_plc_cng = ds.decoded_plc_cng;
    234 
    235   return stats;
    236 }
    237 
    238 void AudioReceiveStream::SetSink(rtc::scoped_ptr<AudioSinkInterface> sink) {
    239   RTC_DCHECK(thread_checker_.CalledOnValidThread());
    240   channel_proxy_->SetSink(std::move(sink));
    241 }
    242 
    243 const webrtc::AudioReceiveStream::Config& AudioReceiveStream::config() const {
    244   RTC_DCHECK(thread_checker_.CalledOnValidThread());
    245   return config_;
    246 }
    247 
    248 VoiceEngine* AudioReceiveStream::voice_engine() const {
    249   internal::AudioState* audio_state =
    250       static_cast<internal::AudioState*>(audio_state_.get());
    251   VoiceEngine* voice_engine = audio_state->voice_engine();
    252   RTC_DCHECK(voice_engine);
    253   return voice_engine;
    254 }
    255 }  // namespace internal
    256 }  // namespace webrtc
    257