Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(139)

Side by Side Diff: webrtc/audio/audio_send_stream.cc

Issue 2705093002: Injectable audio encoders: WebRtcVoiceEngine and company (Closed)
Patch Set: AudioSendStream::Reconfigure() Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/audio/audio_send_stream.h" 11 #include "webrtc/audio/audio_send_stream.h"
12 12
13 #include <string> 13 #include <string>
14 #include <utility>
15 #include <vector>
14 16
15 #include "webrtc/audio/audio_state.h" 17 #include "webrtc/audio/audio_state.h"
16 #include "webrtc/audio/conversion.h" 18 #include "webrtc/audio/conversion.h"
17 #include "webrtc/audio/scoped_voe_interface.h" 19 #include "webrtc/audio/scoped_voe_interface.h"
18 #include "webrtc/base/checks.h" 20 #include "webrtc/base/checks.h"
19 #include "webrtc/base/event.h" 21 #include "webrtc/base/event.h"
22 #include "webrtc/base/function_view.h"
20 #include "webrtc/base/logging.h" 23 #include "webrtc/base/logging.h"
21 #include "webrtc/base/task_queue.h" 24 #include "webrtc/base/task_queue.h"
25 #include "webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.h"
22 #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h" 26 #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
23 #include "webrtc/modules/congestion_controller/include/congestion_controller.h" 27 #include "webrtc/modules/congestion_controller/include/congestion_controller.h"
24 #include "webrtc/modules/pacing/paced_sender.h" 28 #include "webrtc/modules/pacing/paced_sender.h"
25 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" 29 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
26 #include "webrtc/voice_engine/channel_proxy.h" 30 #include "webrtc/voice_engine/channel_proxy.h"
27 #include "webrtc/voice_engine/include/voe_base.h" 31 #include "webrtc/voice_engine/include/voe_base.h"
28 #include "webrtc/voice_engine/transmit_mixer.h" 32 #include "webrtc/voice_engine/transmit_mixer.h"
29 #include "webrtc/voice_engine/voice_engine_impl.h" 33 #include "webrtc/voice_engine/voice_engine_impl.h"
30 34
31 namespace webrtc { 35 namespace webrtc {
32 36
37 namespace internal {
38
33 namespace { 39 namespace {
40 void CallEncoder(const std::unique_ptr<voe::ChannelProxy>& channel_proxy,
41 rtc::FunctionView<void(AudioEncoder*)> lambda) {
42 channel_proxy->ModifyEncoder(
43 [&lambda](std::unique_ptr<AudioEncoder>* encoder_ptr) {
kwiberg-webrtc 2017/04/06 10:13:29 Or just [&]. That way, you make it very plain that
ossu 2017/04/06 11:14:24 I'm all for [&] capture. In this case, capturing t
44 RTC_DCHECK(encoder_ptr);
45 lambda(encoder_ptr->get());
46 });
47 }
48 }
the sun 2017/04/04 23:02:54 nit: // namespace
kwiberg-webrtc 2017/04/06 10:13:29 clang-format will fix this for you nowadays...
ossu 2017/04/06 10:15:21 Acknowledged.
34 49
35 constexpr char kOpusCodecName[] = "opus";
36
37 bool IsCodec(const webrtc::CodecInst& codec, const char* ref_name) {
38 return (STR_CASE_CMP(codec.plname, ref_name) == 0);
39 }
40 } // namespace
41
42 namespace internal {
43 AudioSendStream::AudioSendStream( 50 AudioSendStream::AudioSendStream(
44 const webrtc::AudioSendStream::Config& config, 51 const webrtc::AudioSendStream::Config& config,
45 const rtc::scoped_refptr<webrtc::AudioState>& audio_state, 52 const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
46 rtc::TaskQueue* worker_queue, 53 rtc::TaskQueue* worker_queue,
47 PacketRouter* packet_router, 54 PacketRouter* packet_router,
48 CongestionController* congestion_controller, 55 CongestionController* congestion_controller,
49 BitrateAllocator* bitrate_allocator, 56 BitrateAllocator* bitrate_allocator,
50 RtcEventLog* event_log, 57 RtcEventLog* event_log,
51 RtcpRttStats* rtcp_rtt_stats) 58 RtcpRttStats* rtcp_rtt_stats)
52 : worker_queue_(worker_queue), 59 : worker_queue_(worker_queue),
53 config_(config), 60 config_(config),
54 audio_state_(audio_state), 61 audio_state_(audio_state),
62 event_log_(event_log),
63 packet_router_(packet_router),
55 bitrate_allocator_(bitrate_allocator), 64 bitrate_allocator_(bitrate_allocator),
56 congestion_controller_(congestion_controller) { 65 congestion_controller_(congestion_controller) {
57 LOG(LS_INFO) << "AudioSendStream: " << config_.ToString(); 66 LOG(LS_INFO) << "AudioSendStream: " << config_.ToString();
58 RTC_DCHECK_NE(config_.voe_channel_id, -1); 67 RTC_DCHECK_NE(config_.voe_channel_id, -1);
59 RTC_DCHECK(audio_state_.get()); 68 RTC_DCHECK(audio_state_.get());
60 RTC_DCHECK(congestion_controller); 69 RTC_DCHECK(congestion_controller);
61 70
62 VoiceEngineImpl* voe_impl = static_cast<VoiceEngineImpl*>(voice_engine()); 71 VoiceEngineImpl* voe_impl = static_cast<VoiceEngineImpl*>(voice_engine());
the sun 2017/04/04 23:02:53 Can you call Reconfigure() from here (or the some
ossu 2017/04/06 10:15:21 I considered it but I don't think I'll be able to
63 channel_proxy_ = voe_impl->GetChannelProxy(config_.voe_channel_id); 72 channel_proxy_ = voe_impl->GetChannelProxy(config_.voe_channel_id);
64 channel_proxy_->SetRtcEventLog(event_log); 73 channel_proxy_->SetRtcEventLog(event_log_);
65 channel_proxy_->SetRtcpRttStats(rtcp_rtt_stats); 74 channel_proxy_->SetRtcpRttStats(rtcp_rtt_stats);
66 channel_proxy_->SetRTCPStatus(true); 75 channel_proxy_->SetRTCPStatus(true);
67 channel_proxy_->SetLocalSSRC(config.rtp.ssrc); 76 channel_proxy_->SetLocalSSRC(config.rtp.ssrc);
68 channel_proxy_->SetRTCP_CNAME(config.rtp.c_name); 77 channel_proxy_->SetRTCP_CNAME(config.rtp.c_name);
69 // TODO(solenberg): Config NACK history window (which is a packet count), 78 // TODO(solenberg): Config NACK history window (which is a packet count),
70 // using the actual packet size for the configured codec. 79 // using the actual packet size for the configured codec.
71 channel_proxy_->SetNACKStatus(config_.rtp.nack.rtp_history_ms != 0, 80 channel_proxy_->SetNACKStatus(config_.rtp.nack.rtp_history_ms != 0,
72 config_.rtp.nack.rtp_history_ms / 20); 81 config_.rtp.nack.rtp_history_ms / 20);
73 82
74 channel_proxy_->RegisterExternalTransport(config.send_transport); 83 channel_proxy_->RegisterExternalTransport(config.send_transport);
75 84
76 for (const auto& extension : config.rtp.extensions) { 85 for (const auto& extension : config.rtp.extensions) {
77 if (extension.uri == RtpExtension::kAudioLevelUri) { 86 if (extension.uri == RtpExtension::kAudioLevelUri) {
78 channel_proxy_->SetSendAudioLevelIndicationStatus(true, extension.id); 87 channel_proxy_->SetSendAudioLevelIndicationStatus(true, extension.id);
79 } else if (extension.uri == RtpExtension::kTransportSequenceNumberUri) { 88 } else if (extension.uri == RtpExtension::kTransportSequenceNumberUri) {
80 channel_proxy_->EnableSendTransportSequenceNumber(extension.id); 89 channel_proxy_->EnableSendTransportSequenceNumber(extension.id);
81 congestion_controller->EnablePeriodicAlrProbing(true); 90 congestion_controller->EnablePeriodicAlrProbing(true);
82 bandwidth_observer_.reset(congestion_controller->GetBitrateController() 91 bandwidth_observer_.reset(congestion_controller->GetBitrateController()
83 ->CreateRtcpBandwidthObserver()); 92 ->CreateRtcpBandwidthObserver());
84 } else { 93 } else {
85 RTC_NOTREACHED() << "Registering unsupported RTP extension."; 94 RTC_NOTREACHED() << "Registering unsupported RTP extension.";
86 } 95 }
87 } 96 }
88 channel_proxy_->RegisterSenderCongestionControlObjects( 97 channel_proxy_->RegisterSenderCongestionControlObjects(
89 congestion_controller->pacer(), congestion_controller, packet_router, 98 congestion_controller->pacer(), congestion_controller, packet_router,
90 bandwidth_observer_.get()); 99 bandwidth_observer_.get());
91 if (!SetupSendCodec()) { 100 if (config_.send_codec_spec && !SetupSendCodec(config_)) {
92 LOG(LS_ERROR) << "Failed to set up send codec state."; 101 LOG(LS_ERROR) << "Failed to set up send codec state.";
93 } 102 }
94 } 103 }
95 104
96 AudioSendStream::~AudioSendStream() { 105 AudioSendStream::~AudioSendStream() {
97 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 106 RTC_DCHECK(thread_checker_.CalledOnValidThread());
98 LOG(LS_INFO) << "~AudioSendStream: " << config_.ToString(); 107 LOG(LS_INFO) << "~AudioSendStream: " << config_.ToString();
99 channel_proxy_->DeRegisterExternalTransport(); 108 channel_proxy_->DeRegisterExternalTransport();
100 channel_proxy_->ResetCongestionControlObjects(); 109 channel_proxy_->ResetCongestionControlObjects();
101 channel_proxy_->SetRtcEventLog(nullptr); 110 channel_proxy_->SetRtcEventLog(nullptr);
102 channel_proxy_->SetRtcpRttStats(nullptr); 111 channel_proxy_->SetRtcpRttStats(nullptr);
103 } 112 }
104 113
114 void AudioSendStream::Reconfigure(
the sun 2017/04/04 23:02:53 Many of the lazy-updated attributes here amount to
ossu 2017/04/06 10:15:21 Very little work, and locks. Do you want me to re
the sun 2017/04/06 20:33:47 I think avoiding the duplicated code between here
115 const webrtc::AudioSendStream::Config& new_config) {
116 LOG(LS_INFO) << "AudioSendStream::Reconfigure: " << new_config.ToString();
117 // TODO(ossu): Really enforce SSRC here?
118 RTC_CHECK_EQ(config_.rtp.ssrc, new_config.rtp.ssrc);
119 if (new_config.rtp.c_name != config_.rtp.c_name) {
120 channel_proxy_->SetRTCP_CNAME(new_config.rtp.c_name);
121 }
122 if (new_config.rtp.nack.rtp_history_ms != config_.rtp.nack.rtp_history_ms) {
123 // TODO(solenberg): Config NACK history window (which is a packet count),
124 // using the actual packet size for the configured codec.
125 channel_proxy_->SetNACKStatus(config_.rtp.nack.rtp_history_ms != 0,
126 config_.rtp.nack.rtp_history_ms / 20);
127 }
128
129 if (new_config.send_transport != config_.send_transport) {
130 channel_proxy_->DeRegisterExternalTransport();
131 channel_proxy_->RegisterExternalTransport(new_config.send_transport);
132 }
133
134 // RFC 5285: Each distinct extension MUST have a unique ID. The value 0 is
the sun 2017/04/04 23:02:54 This is already guaranteed by WVoMC::SetSendParame
ossu 2017/04/06 10:15:21 I've added it as an explanation to why I can use 0
135 // reserved for padding and MUST NOT be used as a local identifier.
136 struct ExtensionIds {
137 int audio_level = 0;
138 int transport_sequence_number = 0;
139 };
140
141 auto find_extension_ids = [](const std::vector<RtpExtension>& extensions) {
142 ExtensionIds ids;
143 for (const auto& extension : extensions) {
144 if (extension.uri == RtpExtension::kAudioLevelUri) {
145 ids.audio_level = extension.id;
146 } else if (extension.uri == RtpExtension::kTransportSequenceNumberUri) {
147 ids.transport_sequence_number = extension.id;
148 }
149 }
150 return ids;
151 };
152
153 const ExtensionIds old_ids = find_extension_ids(config_.rtp.extensions);
154 const ExtensionIds new_ids = find_extension_ids(new_config.rtp.extensions);
155 // Audio level indication
156 if (new_ids.audio_level != old_ids.audio_level) {
157 channel_proxy_->SetSendAudioLevelIndicationStatus(new_ids.audio_level != 0,
158 new_ids.audio_level);
159 }
160 // Transport sequence number
161 if (new_ids.transport_sequence_number != old_ids.transport_sequence_number) {
162 channel_proxy_->ResetCongestionControlObjects();
163
164 if (new_ids.transport_sequence_number != 0) {
165 channel_proxy_->EnableSendTransportSequenceNumber(
166 new_ids.transport_sequence_number);
167 congestion_controller_->EnablePeriodicAlrProbing(true);
168 bandwidth_observer_.reset(congestion_controller_->GetBitrateController()
169 ->CreateRtcpBandwidthObserver());
170 } else {
171 bandwidth_observer_.reset();
172 }
173
174 channel_proxy_->RegisterSenderCongestionControlObjects(
175 congestion_controller_->pacer(), congestion_controller_, packet_router_,
176 bandwidth_observer_.get());
177 }
178
179 ReconfigureSendCodec(new_config);
180 ReconfigureBitrateObserver(new_config);
181
182 config_ = new_config;
183 }
184
105 void AudioSendStream::Start() { 185 void AudioSendStream::Start() {
106 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 186 RTC_DCHECK(thread_checker_.CalledOnValidThread());
107 if (config_.min_bitrate_bps != -1 && config_.max_bitrate_bps != -1) { 187 if (config_.min_bitrate_bps != -1 && config_.max_bitrate_bps != -1) {
108 RTC_DCHECK_GE(config_.max_bitrate_bps, config_.min_bitrate_bps); 188 ConfigureBitrateObserver(config_.min_bitrate_bps, config_.max_bitrate_bps);
109 rtc::Event thread_sync_event(false /* manual_reset */, false);
110 worker_queue_->PostTask([this, &thread_sync_event] {
111 bitrate_allocator_->AddObserver(this, config_.min_bitrate_bps,
112 config_.max_bitrate_bps, 0, true);
113 thread_sync_event.Set();
114 });
115 thread_sync_event.Wait(rtc::Event::kForever);
116 } 189 }
117 190
118 ScopedVoEInterface<VoEBase> base(voice_engine()); 191 ScopedVoEInterface<VoEBase> base(voice_engine());
119 int error = base->StartSend(config_.voe_channel_id); 192 int error = base->StartSend(config_.voe_channel_id);
120 if (error != 0) { 193 if (error != 0) {
121 LOG(LS_ERROR) << "AudioSendStream::Start failed with error: " << error; 194 LOG(LS_ERROR) << "AudioSendStream::Start failed with error: " << error;
122 } 195 }
123 } 196 }
124 197
125 void AudioSendStream::Stop() { 198 void AudioSendStream::Stop() {
126 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 199 RTC_DCHECK(thread_checker_.CalledOnValidThread());
127 rtc::Event thread_sync_event(false /* manual_reset */, false); 200 RemoveBitrateObserver();
128 worker_queue_->PostTask([this, &thread_sync_event] {
129 bitrate_allocator_->RemoveObserver(this);
130 thread_sync_event.Set();
131 });
132 thread_sync_event.Wait(rtc::Event::kForever);
133 201
134 ScopedVoEInterface<VoEBase> base(voice_engine()); 202 ScopedVoEInterface<VoEBase> base(voice_engine());
135 int error = base->StopSend(config_.voe_channel_id); 203 int error = base->StopSend(config_.voe_channel_id);
136 if (error != 0) { 204 if (error != 0) {
137 LOG(LS_ERROR) << "AudioSendStream::Stop failed with error: " << error; 205 LOG(LS_ERROR) << "AudioSendStream::Stop failed with error: " << error;
138 } 206 }
139 } 207 }
140 208
141 bool AudioSendStream::SendTelephoneEvent(int payload_type, 209 bool AudioSendStream::SendTelephoneEvent(int payload_type,
142 int payload_frequency, int event, 210 int payload_frequency, int event,
(...skipping 19 matching lines...) Expand all
162 stats.packets_sent = call_stats.packetsSent; 230 stats.packets_sent = call_stats.packetsSent;
163 // RTT isn't known until a RTCP report is received. Until then, VoiceEngine 231 // RTT isn't known until a RTCP report is received. Until then, VoiceEngine
164 // returns 0 to indicate an error value. 232 // returns 0 to indicate an error value.
165 if (call_stats.rttMs > 0) { 233 if (call_stats.rttMs > 0) {
166 stats.rtt_ms = call_stats.rttMs; 234 stats.rtt_ms = call_stats.rttMs;
167 } 235 }
168 // TODO(solenberg): [was ajm]: Re-enable this metric once we have a reliable 236 // TODO(solenberg): [was ajm]: Re-enable this metric once we have a reliable
169 // implementation. 237 // implementation.
170 stats.aec_quality_min = -1; 238 stats.aec_quality_min = -1;
171 239
172 webrtc::CodecInst codec_inst = {0}; 240 if (config_.send_codec_spec) {
173 if (channel_proxy_->GetSendCodec(&codec_inst)) { 241 const auto& spec = *config_.send_codec_spec;
174 RTC_DCHECK_NE(codec_inst.pltype, -1); 242 stats.codec_name = spec.format.name;
175 stats.codec_name = codec_inst.plname; 243 stats.codec_payload_type = rtc::Optional<int>(spec.payload_type);
176 stats.codec_payload_type = rtc::Optional<int>(codec_inst.pltype);
177 244
178 // Get data from the last remote RTCP report. 245 // Get data from the last remote RTCP report.
179 for (const auto& block : channel_proxy_->GetRemoteRTCPReportBlocks()) { 246 for (const auto& block : channel_proxy_->GetRemoteRTCPReportBlocks()) {
180 // Lookup report for send ssrc only. 247 // Lookup report for send ssrc only.
181 if (block.source_SSRC == stats.local_ssrc) { 248 if (block.source_SSRC == stats.local_ssrc) {
182 stats.packets_lost = block.cumulative_num_packets_lost; 249 stats.packets_lost = block.cumulative_num_packets_lost;
183 stats.fraction_lost = Q8ToFloat(block.fraction_lost); 250 stats.fraction_lost = Q8ToFloat(block.fraction_lost);
184 stats.ext_seqnum = block.extended_highest_sequence_number; 251 stats.ext_seqnum = block.extended_highest_sequence_number;
185 // Convert samples to milliseconds. 252 // Convert timestamps to milliseconds.
186 if (codec_inst.plfreq / 1000 > 0) { 253 if (spec.format.clockrate_hz / 1000 > 0) {
187 stats.jitter_ms = 254 stats.jitter_ms =
188 block.interarrival_jitter / (codec_inst.plfreq / 1000); 255 block.interarrival_jitter / (spec.format.clockrate_hz / 1000);
189 } 256 }
190 break; 257 break;
191 } 258 }
192 } 259 }
193 } 260 }
194 261
195 ScopedVoEInterface<VoEBase> base(voice_engine()); 262 ScopedVoEInterface<VoEBase> base(voice_engine());
196 RTC_DCHECK(base->transmit_mixer()); 263 RTC_DCHECK(base->transmit_mixer());
197 stats.audio_level = base->transmit_mixer()->AudioLevelFullRange(); 264 stats.audio_level = base->transmit_mixer()->AudioLevelFullRange();
198 RTC_DCHECK_LE(0, stats.audio_level); 265 RTC_DCHECK_LE(0, stats.audio_level);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 327
261 VoiceEngine* AudioSendStream::voice_engine() const { 328 VoiceEngine* AudioSendStream::voice_engine() const {
262 internal::AudioState* audio_state = 329 internal::AudioState* audio_state =
263 static_cast<internal::AudioState*>(audio_state_.get()); 330 static_cast<internal::AudioState*>(audio_state_.get());
264 VoiceEngine* voice_engine = audio_state->voice_engine(); 331 VoiceEngine* voice_engine = audio_state->voice_engine();
265 RTC_DCHECK(voice_engine); 332 RTC_DCHECK(voice_engine);
266 return voice_engine; 333 return voice_engine;
267 } 334 }
268 335
269 // Apply current codec settings to a single voe::Channel used for sending. 336 // Apply current codec settings to a single voe::Channel used for sending.
270 bool AudioSendStream::SetupSendCodec() { 337 bool AudioSendStream::SetupSendCodec(const Config& config) {
271 // Disable VAD and FEC unless we know the other side wants them. 338 RTC_DCHECK(config.send_codec_spec);
272 channel_proxy_->SetVADStatus(false); 339 // Explicitly hide config_ here, so we don't accidentally setup a send codec
273 channel_proxy_->SetCodecFECStatus(false); 340 // with old parameters.
341 auto setup_encoder = [](const Config& config, RtcEventLog* event_log) {
342 const auto& spec = *config.send_codec_spec;
343 std::unique_ptr<AudioEncoder> encoder =
344 config.encoder_factory->MakeAudioEncoder(spec.payload_type,
345 spec.format);
274 346
275 // We disable audio network adaptor here. This will on one hand make sure that 347 if (!encoder) {
276 // audio network adaptor is disabled by default, and on the other allow audio 348 LOG(LS_ERROR) << "Unable to create encoder for " << spec.format;
277 // network adaptor to be reconfigured, since SetReceiverFrameLengthRange can 349 return encoder;
278 // be only called when audio network adaptor is disabled.
279 channel_proxy_->DisableAudioNetworkAdaptor();
280
281 const auto& send_codec_spec = config_.send_codec_spec;
282
283 // We set the codec first, since the below extra configuration is only applied
284 // to the "current" codec.
285
286 // If codec is already configured, we do not it again.
287 // TODO(minyue): check if this check is really needed, or can we move it into
288 // |codec->SetSendCodec|.
289 webrtc::CodecInst current_codec = {0};
290 if (!channel_proxy_->GetSendCodec(&current_codec) ||
291 (send_codec_spec.codec_inst != current_codec)) {
292 if (!channel_proxy_->SetSendCodec(send_codec_spec.codec_inst)) {
293 LOG(LS_WARNING) << "SetSendCodec() failed.";
294 return false;
295 } 350 }
296 } 351 // If a bitrate has been specified for the codec, use it over the
297 352 // codec's default.
298 // Codec internal FEC. Treat any failure as fatal internal error. 353 if (spec.target_bitrate_bps) {
299 if (send_codec_spec.enable_codec_fec) { 354 encoder->OnReceivedTargetAudioBitrate(*spec.target_bitrate_bps);
300 if (!channel_proxy_->SetCodecFECStatus(true)) {
301 LOG(LS_WARNING) << "SetCodecFECStatus() failed.";
302 return false;
303 }
304 }
305
306 // DTX and maxplaybackrate are only set if current codec is Opus.
307 if (IsCodec(send_codec_spec.codec_inst, kOpusCodecName)) {
308 if (!channel_proxy_->SetOpusDtx(send_codec_spec.enable_opus_dtx)) {
309 LOG(LS_WARNING) << "SetOpusDtx() failed.";
310 return false;
311 } 355 }
312 356
313 // If opus_max_playback_rate <= 0, the default maximum playback rate 357 // Enable ANA if configured (currently only used by Opus).
314 // (48 kHz) will be used. 358 if (config.audio_network_adaptor_config) {
315 if (send_codec_spec.opus_max_playback_rate > 0) { 359 if (encoder->EnableAudioNetworkAdaptor(
316 if (!channel_proxy_->SetOpusMaxPlaybackRate( 360 *config.audio_network_adaptor_config, event_log,
317 send_codec_spec.opus_max_playback_rate)) { 361 Clock::GetRealTimeClock())) {
318 LOG(LS_WARNING) << "SetOpusMaxPlaybackRate() failed."; 362 LOG(LS_INFO) << "Audio network adaptor enabled on SSRC "
319 return false; 363 << config.rtp.ssrc;
364 } else {
365 RTC_NOTREACHED();
320 } 366 }
321 } 367 }
322 368
323 if (config_.audio_network_adaptor_config) { 369 // Wrap the encoder in a an AudioEncoderCNG, if VAD is enabled.
324 // Audio network adaptor is only allowed for Opus currently. 370 if (spec.cng_payload_type) {
325 // |SetReceiverFrameLengthRange| needs to be called before 371 AudioEncoderCng::Config cng_config;
326 // |EnableAudioNetworkAdaptor|. 372 cng_config.num_channels = encoder->NumChannels();
327 channel_proxy_->SetReceiverFrameLengthRange(send_codec_spec.min_ptime_ms, 373 cng_config.payload_type = *spec.cng_payload_type;
328 send_codec_spec.max_ptime_ms); 374 cng_config.speech_encoder = std::move(encoder);
329 channel_proxy_->EnableAudioNetworkAdaptor( 375 cng_config.vad_mode = Vad::kVadNormal;
330 *config_.audio_network_adaptor_config); 376 encoder.reset(new AudioEncoderCng(std::move(cng_config)));
331 LOG(LS_INFO) << "Audio network adaptor enabled on SSRC "
332 << config_.rtp.ssrc;
333 } 377 }
378
379 return encoder;
380 };
381
382 auto encoder = setup_encoder(config, event_log_);
383 if (!encoder) {
384 return false;
385 }
386 channel_proxy_->SetEncoder(config.send_codec_spec->payload_type,
387 std::move(encoder));
388 return true;
389 }
390
391 bool AudioSendStream::ReconfigureSendCodec(const Config& new_config) {
392 if (new_config.send_codec_spec == config_.send_codec_spec) {
393 return true;
334 } 394 }
335 395
336 // Set the CN payloadtype and the VAD status. 396 // If we have no encoder, or the format or payload type's changed, create a
337 if (send_codec_spec.cng_payload_type != -1) { 397 // new encoder.
338 // The CN payload type for 8000 Hz clockrate is fixed at 13. 398 if (!config_.send_codec_spec ||
339 if (send_codec_spec.cng_plfreq != 8000) { 399 new_config.send_codec_spec->format != config_.send_codec_spec->format ||
340 webrtc::PayloadFrequencies cn_freq; 400 new_config.send_codec_spec->payload_type !=
341 switch (send_codec_spec.cng_plfreq) { 401 config_.send_codec_spec->payload_type) {
342 case 16000: 402 return SetupSendCodec(new_config);
343 cn_freq = webrtc::kFreq16000Hz; 403 }
344 break; 404
345 case 32000: 405 if (!new_config.send_codec_spec) {
346 cn_freq = webrtc::kFreq32000Hz; 406 // TODO(ossu): Double-check this!
347 break; 407 LOG(LS_ERROR) << "Cannot replace the current encoder with no encoder";
348 default: 408 RTC_NOTREACHED();
349 RTC_NOTREACHED(); 409 return false;
350 return false; 410 }
411
412 const rtc::Optional<int>& new_target_bitrate_bps =
413 new_config.send_codec_spec->target_bitrate_bps;
414 // If a bitrate has been specified for the codec, use it over the
415 // codec's default.
416 if (new_target_bitrate_bps &&
417 new_target_bitrate_bps != config_.send_codec_spec->target_bitrate_bps) {
418 CallEncoder(channel_proxy_, [&](AudioEncoder* encoder) {
419 encoder->OnReceivedTargetAudioBitrate(*new_target_bitrate_bps);
420 });
421 }
422
423 ReconfigureANA(new_config);
424 ReconfigureCNG(new_config);
425
426 return true;
427 }
428
429 void AudioSendStream::ReconfigureANA(const Config& new_config) {
430 if (new_config.audio_network_adaptor_config ==
431 config_.audio_network_adaptor_config) {
432 return;
433 }
434 if (new_config.audio_network_adaptor_config) {
435 CallEncoder(channel_proxy_, [&](AudioEncoder* encoder) {
436 if (encoder->EnableAudioNetworkAdaptor(
437 *new_config.audio_network_adaptor_config, event_log_,
438 Clock::GetRealTimeClock())) {
439 LOG(LS_INFO) << "Audio network adaptor enabled on SSRC "
440 << new_config.rtp.ssrc;
441 } else {
442 RTC_NOTREACHED();
351 } 443 }
352 if (!channel_proxy_->SetSendCNPayloadType( 444 });
353 send_codec_spec.cng_payload_type, cn_freq)) { 445 } else {
354 LOG(LS_WARNING) << "SetSendCNPayloadType() failed."; 446 CallEncoder(channel_proxy_, [&](AudioEncoder* encoder) {
355 // TODO(ajm): This failure condition will be removed from VoE. 447 encoder->DisableAudioNetworkAdaptor();
356 // Restore the return here when we update to a new enough webrtc. 448 });
357 // 449 LOG(LS_INFO) << "Audio network adaptor disabled on SSRC "
358 // Not returning false because the SetSendCNPayloadType will fail if 450 << new_config.rtp.ssrc;
359 // the channel is already sending. 451 }
360 // This can happen if the remote description is applied twice, for 452 }
361 // example in the case of ROAP on top of JSEP, where both side will
362 // send the offer.
363 }
364 }
365 453
366 // Only turn on VAD if we have a CN payload type that matches the 454 void AudioSendStream::ReconfigureCNG(const Config& new_config) {
367 // clockrate for the codec we are going to use. 455 if (new_config.send_codec_spec->cng_payload_type ==
368 if (send_codec_spec.cng_plfreq == send_codec_spec.codec_inst.plfreq && 456 config_.send_codec_spec->cng_payload_type) {
369 send_codec_spec.codec_inst.channels == 1) { 457 return;
370 // TODO(minyue): If CN frequency == 48000 Hz is allowed, consider the
371 // interaction between VAD and Opus FEC.
372 if (!channel_proxy_->SetVADStatus(true)) {
373 LOG(LS_WARNING) << "SetVADStatus() failed.";
374 return false;
375 }
376 }
377 } 458 }
378 return true; 459
460 // Wrap or unwrap the encoder in an AudioEncoderCNG.
461 channel_proxy_->ModifyEncoder(
462 [&](std::unique_ptr<AudioEncoder>* encoder_ptr) {
463 std::unique_ptr<AudioEncoder> old_encoder(std::move(*encoder_ptr));
464 auto sub_encoders = old_encoder->ReclaimContainedEncoders();
kwiberg-webrtc 2017/04/06 10:13:29 Eugh. I'm having second thoughts about having this
ossu 2017/04/06 11:14:24 Yeah, it's a bit nasty, but slightly less so in th
465 if (!sub_encoders.empty()) {
466 // Replace enc with its sub encoder. We need to put the sub
467 // encoder in a temporary first, since otherwise the old value
468 // of enc would be destroyed before the new value got assigned,
469 // which would be bad since the new value is a part of the old
470 // value.
471 auto tmp = std::move(sub_encoders[0]);
472 old_encoder = std::move(tmp);
473 }
474 if (new_config.send_codec_spec->cng_payload_type) {
475 AudioEncoderCng::Config config;
476 config.speech_encoder = std::move(old_encoder);
477 config.num_channels = config.speech_encoder->NumChannels();
478 config.payload_type = *new_config.send_codec_spec->cng_payload_type;
479 config.vad_mode = Vad::kVadNormal;
480 encoder_ptr->reset(new AudioEncoderCng(std::move(config)));
481 } else {
482 *encoder_ptr = std::move(old_encoder);
483 }
484 });
485 }
486
487 void AudioSendStream::ReconfigureBitrateObserver(
488 const webrtc::AudioSendStream::Config& new_config) {
489 if (config_.min_bitrate_bps == new_config.min_bitrate_bps &&
490 config_.max_bitrate_bps == new_config.max_bitrate_bps) {
491 return;
492 }
493
494 if (new_config.min_bitrate_bps != -1 && new_config.max_bitrate_bps != -1) {
ossu 2017/04/04 15:36:38 Do I need to check if we're sending here first? Th
495 ConfigureBitrateObserver(config_.min_bitrate_bps, config_.max_bitrate_bps);
496 } else {
497 RemoveBitrateObserver();
498 }
499 }
500
501 void AudioSendStream::ConfigureBitrateObserver(int min_bitrate_bps,
502 int max_bitrate_bps) {
503 RTC_DCHECK(thread_checker_.CalledOnValidThread());
504 RTC_DCHECK_GE(max_bitrate_bps, min_bitrate_bps);
505 rtc::Event thread_sync_event(false /* manual_reset */, false);
506 worker_queue_->PostTask([&] {
507 bitrate_allocator_->AddObserver(this, min_bitrate_bps, max_bitrate_bps, 0,
508 true);
509 thread_sync_event.Set();
510 });
511 thread_sync_event.Wait(rtc::Event::kForever);
512 }
513
514 void AudioSendStream::RemoveBitrateObserver() {
515 RTC_DCHECK(thread_checker_.CalledOnValidThread());
516 rtc::Event thread_sync_event(false /* manual_reset */, false);
517 worker_queue_->PostTask([this, &thread_sync_event] {
518 bitrate_allocator_->RemoveObserver(this);
519 thread_sync_event.Set();
520 });
521 thread_sync_event.Wait(rtc::Event::kForever);
379 } 522 }
380 523
381 } // namespace internal 524 } // namespace internal
382 } // namespace webrtc 525 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698