diff options
Diffstat (limited to 'webrtc/audio/audio_send_stream.cc')
-rw-r--r-- | webrtc/audio/audio_send_stream.cc | 185 |
1 files changed, 112 insertions, 73 deletions
diff --git a/webrtc/audio/audio_send_stream.cc b/webrtc/audio/audio_send_stream.cc index ccfdca546d..35a65521dd 100644 --- a/webrtc/audio/audio_send_stream.cc +++ b/webrtc/audio/audio_send_stream.cc @@ -12,13 +12,20 @@ #include <string> +#include "webrtc/audio/audio_state.h" #include "webrtc/audio/conversion.h" +#include "webrtc/audio/scoped_voe_interface.h" #include "webrtc/base/checks.h" #include "webrtc/base/logging.h" +#include "webrtc/call/congestion_controller.h" +#include "webrtc/modules/pacing/paced_sender.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" +#include "webrtc/voice_engine/channel_proxy.h" #include "webrtc/voice_engine/include/voe_audio_processing.h" #include "webrtc/voice_engine/include/voe_codec.h" #include "webrtc/voice_engine/include/voe_rtp_rtcp.h" #include "webrtc/voice_engine/include/voe_volume_control.h" +#include "webrtc/voice_engine/voice_engine_impl.h" namespace webrtc { std::string AudioSendStream::Config::Rtp::ToString() const { @@ -32,6 +39,7 @@ std::string AudioSendStream::Config::Rtp::ToString() const { } } ss << ']'; + ss << ", c_name: " << c_name; ss << '}'; return ss.str(); } @@ -48,38 +56,91 @@ std::string AudioSendStream::Config::ToString() const { } namespace internal { -AudioSendStream::AudioSendStream(const webrtc::AudioSendStream::Config& config, - VoiceEngine* voice_engine) - : config_(config), - voice_engine_(voice_engine), - voe_base_(voice_engine) { +AudioSendStream::AudioSendStream( + const webrtc::AudioSendStream::Config& config, + const rtc::scoped_refptr<webrtc::AudioState>& audio_state, + CongestionController* congestion_controller) + : config_(config), audio_state_(audio_state) { LOG(LS_INFO) << "AudioSendStream: " << config_.ToString(); - RTC_DCHECK_NE(config.voe_channel_id, -1); - RTC_DCHECK(voice_engine_); + RTC_DCHECK_NE(config_.voe_channel_id, -1); + RTC_DCHECK(audio_state_.get()); + RTC_DCHECK(congestion_controller); + + VoiceEngineImpl* voe_impl = static_cast<VoiceEngineImpl*>(voice_engine()); + channel_proxy_ = voe_impl->GetChannelProxy(config_.voe_channel_id); + channel_proxy_->SetCongestionControlObjects( + congestion_controller->pacer(), + congestion_controller->GetTransportFeedbackObserver(), + congestion_controller->packet_router()); + channel_proxy_->SetRTCPStatus(true); + channel_proxy_->SetLocalSSRC(config.rtp.ssrc); + channel_proxy_->SetRTCP_CNAME(config.rtp.c_name); + + for (const auto& extension : config.rtp.extensions) { + if (extension.name == RtpExtension::kAbsSendTime) { + channel_proxy_->SetSendAbsoluteSenderTimeStatus(true, extension.id); + } else if (extension.name == RtpExtension::kAudioLevel) { + channel_proxy_->SetSendAudioLevelIndicationStatus(true, extension.id); + } else if (extension.name == RtpExtension::kTransportSequenceNumber) { + channel_proxy_->EnableSendTransportSequenceNumber(extension.id); + } else { + RTC_NOTREACHED() << "Registering unsupported RTP extension."; + } + } } AudioSendStream::~AudioSendStream() { RTC_DCHECK(thread_checker_.CalledOnValidThread()); LOG(LS_INFO) << "~AudioSendStream: " << config_.ToString(); + channel_proxy_->SetCongestionControlObjects(nullptr, nullptr, nullptr); +} + +void AudioSendStream::Start() { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); +} + +void AudioSendStream::Stop() { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); +} + +void AudioSendStream::SignalNetworkState(NetworkState state) { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); +} + +bool AudioSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { + // TODO(solenberg): Tests call this function on a network thread, libjingle + // calls on the worker thread. We should move towards always using a network + // thread. Then this check can be enabled. + // RTC_DCHECK(!thread_checker_.CalledOnValidThread()); + return false; +} + +bool AudioSendStream::SendTelephoneEvent(int payload_type, uint8_t event, + uint32_t duration_ms) { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); + return channel_proxy_->SetSendTelephoneEventPayloadType(payload_type) && + channel_proxy_->SendTelephoneEventOutband(event, duration_ms); } webrtc::AudioSendStream::Stats AudioSendStream::GetStats() const { RTC_DCHECK(thread_checker_.CalledOnValidThread()); webrtc::AudioSendStream::Stats stats; stats.local_ssrc = config_.rtp.ssrc; - ScopedVoEInterface<VoEAudioProcessing> processing(voice_engine_); - ScopedVoEInterface<VoECodec> codec(voice_engine_); - ScopedVoEInterface<VoERTP_RTCP> rtp(voice_engine_); - ScopedVoEInterface<VoEVolumeControl> volume(voice_engine_); - unsigned int ssrc = 0; - webrtc::CallStatistics call_stats = {0}; - if (rtp->GetLocalSSRC(config_.voe_channel_id, ssrc) == -1 || - rtp->GetRTCPStatistics(config_.voe_channel_id, call_stats) == -1) { - return stats; - } + ScopedVoEInterface<VoEAudioProcessing> processing(voice_engine()); + ScopedVoEInterface<VoECodec> codec(voice_engine()); + ScopedVoEInterface<VoEVolumeControl> volume(voice_engine()); + webrtc::CallStatistics call_stats = channel_proxy_->GetRTCPStatistics(); stats.bytes_sent = call_stats.bytesSent; stats.packets_sent = call_stats.packetsSent; + // RTT isn't known until a RTCP report is received. Until then, VoiceEngine + // returns 0 to indicate an error value. + if (call_stats.rttMs > 0) { + stats.rtt_ms = call_stats.rttMs; + } + // TODO(solenberg): [was ajm]: Re-enable this metric once we have a reliable + // implementation. + stats.aec_quality_min = -1; webrtc::CodecInst codec_inst = {0}; if (codec->GetSendCodec(config_.voe_channel_id, codec_inst) != -1) { @@ -87,54 +148,43 @@ webrtc::AudioSendStream::Stats AudioSendStream::GetStats() const { stats.codec_name = codec_inst.plname; // Get data from the last remote RTCP report. - std::vector<webrtc::ReportBlock> blocks; - if (rtp->GetRemoteRTCPReportBlocks(config_.voe_channel_id, &blocks) != -1) { - for (const webrtc::ReportBlock& block : blocks) { - // Lookup report for send ssrc only. - if (block.source_SSRC == stats.local_ssrc) { - stats.packets_lost = block.cumulative_num_packets_lost; - stats.fraction_lost = Q8ToFloat(block.fraction_lost); - stats.ext_seqnum = block.extended_highest_sequence_number; - // Convert samples to milliseconds. - if (codec_inst.plfreq / 1000 > 0) { - stats.jitter_ms = - block.interarrival_jitter / (codec_inst.plfreq / 1000); - } - break; + for (const auto& block : channel_proxy_->GetRemoteRTCPReportBlocks()) { + // Lookup report for send ssrc only. + if (block.source_SSRC == stats.local_ssrc) { + stats.packets_lost = block.cumulative_num_packets_lost; + stats.fraction_lost = Q8ToFloat(block.fraction_lost); + stats.ext_seqnum = block.extended_highest_sequence_number; + // Convert samples to milliseconds. + if (codec_inst.plfreq / 1000 > 0) { + stats.jitter_ms = + block.interarrival_jitter / (codec_inst.plfreq / 1000); } + break; } } } - // RTT isn't known until a RTCP report is received. Until then, VoiceEngine - // returns 0 to indicate an error value. - if (call_stats.rttMs > 0) { - stats.rtt_ms = call_stats.rttMs; - } - // Local speech level. { unsigned int level = 0; - if (volume->GetSpeechInputLevelFullRange(level) != -1) { - stats.audio_level = static_cast<int32_t>(level); - } + int error = volume->GetSpeechInputLevelFullRange(level); + RTC_DCHECK_EQ(0, error); + stats.audio_level = static_cast<int32_t>(level); } - // TODO(ajm): Re-enable this metric once we have a reliable implementation. - stats.aec_quality_min = -1; - bool echo_metrics_on = false; - if (processing->GetEcMetricsStatus(echo_metrics_on) != -1 && - echo_metrics_on) { + int error = processing->GetEcMetricsStatus(echo_metrics_on); + RTC_DCHECK_EQ(0, error); + if (echo_metrics_on) { // These can also be negative, but in practice -1 is only used to signal // insufficient data, since the resolution is limited to multiples of 4 ms. int median = -1; int std = -1; float dummy = 0.0f; - if (processing->GetEcDelayMetrics(median, std, dummy) != -1) { - stats.echo_delay_median_ms = median; - stats.echo_delay_std_ms = std; - } + error = processing->GetEcDelayMetrics(median, std, dummy); + RTC_DCHECK_EQ(0, error); + stats.echo_delay_median_ms = median; + stats.echo_delay_std_ms = std; // These can take on valid negative values, so use the lowest possible level // as default rather than -1. @@ -142,14 +192,15 @@ webrtc::AudioSendStream::Stats AudioSendStream::GetStats() const { int erle = -100; int dummy1 = 0; int dummy2 = 0; - if (processing->GetEchoMetrics(erl, erle, dummy1, dummy2) != -1) { - stats.echo_return_loss = erl; - stats.echo_return_loss_enhancement = erle; - } + error = processing->GetEchoMetrics(erl, erle, dummy1, dummy2); + RTC_DCHECK_EQ(0, error); + stats.echo_return_loss = erl; + stats.echo_return_loss_enhancement = erle; } - // TODO(solenberg): Collect typing noise warnings here too! - // bool typing_noise_detected = typing_noise_detected_; + internal::AudioState* audio_state = + static_cast<internal::AudioState*>(audio_state_.get()); + stats.typing_noise_detected = audio_state->typing_noise_detected(); return stats; } @@ -159,24 +210,12 @@ const webrtc::AudioSendStream::Config& AudioSendStream::config() const { return config_; } -void AudioSendStream::Start() { - RTC_DCHECK(thread_checker_.CalledOnValidThread()); -} - -void AudioSendStream::Stop() { - RTC_DCHECK(thread_checker_.CalledOnValidThread()); -} - -void AudioSendStream::SignalNetworkState(NetworkState state) { - RTC_DCHECK(thread_checker_.CalledOnValidThread()); -} - -bool AudioSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { - // TODO(solenberg): Tests call this function on a network thread, libjingle - // calls on the worker thread. We should move towards always using a network - // thread. Then this check can be enabled. - // RTC_DCHECK(!thread_checker_.CalledOnValidThread()); - return false; +VoiceEngine* AudioSendStream::voice_engine() const { + internal::AudioState* audio_state = + static_cast<internal::AudioState*>(audio_state_.get()); + VoiceEngine* voice_engine = audio_state->voice_engine(); + RTC_DCHECK(voice_engine); + return voice_engine; } } // namespace internal } // namespace webrtc |