aboutsummaryrefslogtreecommitdiff
path: root/webrtc/audio/audio_send_stream.cc
diff options
context:
space:
mode:
Diffstat (limited to 'webrtc/audio/audio_send_stream.cc')
-rw-r--r--webrtc/audio/audio_send_stream.cc185
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