LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/audio - audio_receive_stream.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 182 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 21 0.0 %
Legend: Lines: hit not hit

          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

Generated by: LCOV version 1.13