OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2004 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 |
(...skipping 19 matching lines...) Expand all Loading... | |
30 #include "webrtc/base/stringutils.h" | 30 #include "webrtc/base/stringutils.h" |
31 #include "webrtc/base/trace_event.h" | 31 #include "webrtc/base/trace_event.h" |
32 #include "webrtc/media/base/audiosource.h" | 32 #include "webrtc/media/base/audiosource.h" |
33 #include "webrtc/media/base/mediaconstants.h" | 33 #include "webrtc/media/base/mediaconstants.h" |
34 #include "webrtc/media/base/streamparams.h" | 34 #include "webrtc/media/base/streamparams.h" |
35 #include "webrtc/media/engine/payload_type_mapper.h" | 35 #include "webrtc/media/engine/payload_type_mapper.h" |
36 #include "webrtc/media/engine/webrtcmediaengine.h" | 36 #include "webrtc/media/engine/webrtcmediaengine.h" |
37 #include "webrtc/media/engine/webrtcvoe.h" | 37 #include "webrtc/media/engine/webrtcvoe.h" |
38 #include "webrtc/modules/audio_coding/acm2/rent_a_codec.h" | 38 #include "webrtc/modules/audio_coding/acm2/rent_a_codec.h" |
39 #include "webrtc/modules/audio_mixer/audio_mixer_impl.h" | 39 #include "webrtc/modules/audio_mixer/audio_mixer_impl.h" |
40 #include "webrtc/modules/audio_coding/codecs/builtin_audio_encoder_factory.h" | |
40 #include "webrtc/modules/audio_processing/include/audio_processing.h" | 41 #include "webrtc/modules/audio_processing/include/audio_processing.h" |
41 #include "webrtc/system_wrappers/include/field_trial.h" | 42 #include "webrtc/system_wrappers/include/field_trial.h" |
42 #include "webrtc/system_wrappers/include/trace.h" | 43 #include "webrtc/system_wrappers/include/trace.h" |
43 | 44 |
44 namespace cricket { | 45 namespace cricket { |
45 namespace { | 46 namespace { |
46 | 47 |
47 const int kDefaultTraceFilter = webrtc::kTraceNone | webrtc::kTraceTerseInfo | | 48 const int kDefaultTraceFilter = webrtc::kTraceNone | webrtc::kTraceTerseInfo | |
48 webrtc::kTraceWarning | webrtc::kTraceError | | 49 webrtc::kTraceWarning | webrtc::kTraceError | |
49 webrtc::kTraceCritical; | 50 webrtc::kTraceCritical; |
(...skipping 15 matching lines...) Expand all Loading... | |
65 constexpr int kNackRtpHistoryMs = 5000; | 66 constexpr int kNackRtpHistoryMs = 5000; |
66 | 67 |
67 // Check to verify that the define for the intelligibility enhancer is properly | 68 // Check to verify that the define for the intelligibility enhancer is properly |
68 // set. | 69 // set. |
69 #if !defined(WEBRTC_INTELLIGIBILITY_ENHANCER) || \ | 70 #if !defined(WEBRTC_INTELLIGIBILITY_ENHANCER) || \ |
70 (WEBRTC_INTELLIGIBILITY_ENHANCER != 0 && \ | 71 (WEBRTC_INTELLIGIBILITY_ENHANCER != 0 && \ |
71 WEBRTC_INTELLIGIBILITY_ENHANCER != 1) | 72 WEBRTC_INTELLIGIBILITY_ENHANCER != 1) |
72 #error "Set WEBRTC_INTELLIGIBILITY_ENHANCER to either 0 or 1" | 73 #error "Set WEBRTC_INTELLIGIBILITY_ENHANCER to either 0 or 1" |
73 #endif | 74 #endif |
74 | 75 |
75 // Codec parameters for Opus. | 76 // For SendSideBwe, Opus bitrate should be in the range between 6000 and 32000. |
76 // draft-spittka-payload-rtp-opus-03 | 77 const int kOpusMinBitrateBps = 6000; |
77 | |
78 // Recommended bitrates: | |
79 // 8-12 kb/s for NB speech, | |
80 // 16-20 kb/s for WB speech, | |
81 // 28-40 kb/s for FB speech, | |
82 // 48-64 kb/s for FB mono music, and | |
83 // 64-128 kb/s for FB stereo music. | |
84 // The current implementation applies the following values to mono signals, | |
85 // and multiplies them by 2 for stereo. | |
86 const int kOpusBitrateNbBps = 12000; | |
87 const int kOpusBitrateWbBps = 20000; | |
88 const int kOpusBitrateFbBps = 32000; | 78 const int kOpusBitrateFbBps = 32000; |
89 | 79 |
90 // Opus bitrate should be in the range between 6000 and 510000. | |
91 const int kOpusMinBitrateBps = 6000; | |
92 const int kOpusMaxBitrateBps = 510000; | |
93 | |
94 // iSAC bitrate should be <= 56000. | |
95 const int kIsacMaxBitrateBps = 56000; | |
96 | |
97 // Default audio dscp value. | 80 // Default audio dscp value. |
98 // See http://tools.ietf.org/html/rfc2474 for details. | 81 // See http://tools.ietf.org/html/rfc2474 for details. |
99 // See also http://tools.ietf.org/html/draft-jennings-rtcweb-qos-00 | 82 // See also http://tools.ietf.org/html/draft-jennings-rtcweb-qos-00 |
100 const rtc::DiffServCodePoint kAudioDscpValue = rtc::DSCP_EF; | 83 const rtc::DiffServCodePoint kAudioDscpValue = rtc::DSCP_EF; |
101 | 84 |
102 // Constants from voice_engine_defines.h. | 85 // Constants from voice_engine_defines.h. |
103 const int kMinTelephoneEventCode = 0; // RFC4733 (Section 2.3.1) | 86 const int kMinTelephoneEventCode = 0; // RFC4733 (Section 2.3.1) |
104 const int kMaxTelephoneEventCode = 255; | 87 const int kMaxTelephoneEventCode = 255; |
105 const int kMinTelephoneEventDuration = 100; | 88 const int kMinTelephoneEventDuration = 100; |
106 const int kMaxTelephoneEventDuration = 60000; // Actual limit is 2^16 | 89 const int kMaxTelephoneEventDuration = 60000; // Actual limit is 2^16 |
(...skipping 19 matching lines...) Expand all Loading... | |
126 if (sp.ssrcs.size() > 1) { | 109 if (sp.ssrcs.size() > 1) { |
127 LOG(LS_ERROR) << "Multiple SSRCs in stream parameters: " << sp.ToString(); | 110 LOG(LS_ERROR) << "Multiple SSRCs in stream parameters: " << sp.ToString(); |
128 return false; | 111 return false; |
129 } | 112 } |
130 return true; | 113 return true; |
131 } | 114 } |
132 | 115 |
133 // Dumps an AudioCodec in RFC 2327-ish format. | 116 // Dumps an AudioCodec in RFC 2327-ish format. |
134 std::string ToString(const AudioCodec& codec) { | 117 std::string ToString(const AudioCodec& codec) { |
135 std::stringstream ss; | 118 std::stringstream ss; |
136 ss << codec.name << "/" << codec.clockrate << "/" << codec.channels | 119 ss << codec.name << "/" << codec.clockrate << "/" << codec.channels; |
137 << " (" << codec.id << ")"; | 120 ss << " {"; |
121 for (const auto& param : codec.params) { | |
122 ss << " " << param.first << "=" << param.second; | |
123 } | |
124 ss << " }"; | |
125 ss << " (" << codec.id << ")"; | |
138 return ss.str(); | 126 return ss.str(); |
139 } | 127 } |
140 | 128 |
141 std::string ToString(const webrtc::CodecInst& codec) { | 129 std::string ToString(const webrtc::CodecInst& codec) { |
142 std::stringstream ss; | 130 std::stringstream ss; |
143 ss << codec.plname << "/" << codec.plfreq << "/" << codec.channels | 131 ss << codec.plname << "/" << codec.plfreq << "/" << codec.channels |
144 << " (" << codec.pltype << ")"; | 132 << " (" << codec.pltype << ")"; |
145 return ss.str(); | 133 return ss.str(); |
146 } | 134 } |
147 | 135 |
(...skipping 25 matching lines...) Expand all Loading... | |
173 } | 161 } |
174 std::vector<int> payload_types; | 162 std::vector<int> payload_types; |
175 for (const AudioCodec& codec : codecs) { | 163 for (const AudioCodec& codec : codecs) { |
176 payload_types.push_back(codec.id); | 164 payload_types.push_back(codec.id); |
177 } | 165 } |
178 std::sort(payload_types.begin(), payload_types.end()); | 166 std::sort(payload_types.begin(), payload_types.end()); |
179 auto it = std::unique(payload_types.begin(), payload_types.end()); | 167 auto it = std::unique(payload_types.begin(), payload_types.end()); |
180 return it == payload_types.end(); | 168 return it == payload_types.end(); |
181 } | 169 } |
182 | 170 |
183 // Return true if codec.params[feature] == "1", false otherwise. | |
184 bool IsCodecFeatureEnabled(const AudioCodec& codec, const char* feature) { | |
185 int value; | |
186 return codec.GetParam(feature, &value) && value == 1; | |
187 } | |
188 | |
189 rtc::Optional<std::string> GetAudioNetworkAdaptorConfig( | 171 rtc::Optional<std::string> GetAudioNetworkAdaptorConfig( |
190 const AudioOptions& options) { | 172 const AudioOptions& options) { |
191 if (options.audio_network_adaptor && *options.audio_network_adaptor && | 173 if (options.audio_network_adaptor && *options.audio_network_adaptor && |
192 options.audio_network_adaptor_config) { | 174 options.audio_network_adaptor_config) { |
193 // Turn on audio network adaptor only when |options_.audio_network_adaptor| | 175 // Turn on audio network adaptor only when |options_.audio_network_adaptor| |
194 // equals true and |options_.audio_network_adaptor_config| has a value. | 176 // equals true and |options_.audio_network_adaptor_config| has a value. |
195 return options.audio_network_adaptor_config; | 177 return options.audio_network_adaptor_config; |
196 } | 178 } |
197 return rtc::Optional<std::string>(); | 179 return rtc::Optional<std::string>(); |
198 } | 180 } |
199 | 181 |
200 // Returns integer parameter params[feature] if it is defined. Returns | |
201 // |default_value| otherwise. | |
202 int GetCodecFeatureInt(const AudioCodec& codec, | |
203 const char* feature, | |
204 int default_value) { | |
205 int value = 0; | |
206 if (codec.GetParam(feature, &value)) { | |
207 return value; | |
208 } | |
209 return default_value; | |
210 } | |
211 | |
212 // Use params[kCodecParamMaxAverageBitrate] if it is defined, use codec.bitrate | |
213 // otherwise. If the value (either from params or codec.bitrate) <=0, use the | |
214 // default configuration. If the value is beyond feasible bit rate of Opus, | |
215 // clamp it. Returns the Opus bit rate for operation. | |
216 int GetOpusBitrate(const AudioCodec& codec, int max_playback_rate) { | |
217 int bitrate = 0; | |
218 bool use_param = true; | |
219 if (!codec.GetParam(kCodecParamMaxAverageBitrate, &bitrate)) { | |
220 bitrate = codec.bitrate; | |
221 use_param = false; | |
222 } | |
223 if (bitrate <= 0) { | |
224 if (max_playback_rate <= 8000) { | |
225 bitrate = kOpusBitrateNbBps; | |
226 } else if (max_playback_rate <= 16000) { | |
227 bitrate = kOpusBitrateWbBps; | |
228 } else { | |
229 bitrate = kOpusBitrateFbBps; | |
230 } | |
231 | |
232 if (IsCodecFeatureEnabled(codec, kCodecParamStereo)) { | |
233 bitrate *= 2; | |
234 } | |
235 } else if (bitrate < kOpusMinBitrateBps || bitrate > kOpusMaxBitrateBps) { | |
236 bitrate = (bitrate < kOpusMinBitrateBps) ? kOpusMinBitrateBps | |
237 : kOpusMaxBitrateBps; | |
238 std::string rate_source = | |
239 use_param ? "Codec parameter \"maxaveragebitrate\"" : | |
240 "Supplied Opus bitrate"; | |
241 LOG(LS_WARNING) << rate_source | |
242 << " is invalid and is replaced by: " | |
243 << bitrate; | |
244 } | |
245 return bitrate; | |
246 } | |
247 | |
248 void GetOpusConfig(const AudioCodec& codec, | |
249 webrtc::CodecInst* voe_codec, | |
250 bool* enable_codec_fec, | |
251 int* max_playback_rate, | |
252 bool* enable_codec_dtx, | |
253 int* min_ptime_ms, | |
254 int* max_ptime_ms) { | |
255 *enable_codec_fec = IsCodecFeatureEnabled(codec, kCodecParamUseInbandFec); | |
256 *enable_codec_dtx = IsCodecFeatureEnabled(codec, kCodecParamUseDtx); | |
257 *max_playback_rate = GetCodecFeatureInt(codec, kCodecParamMaxPlaybackRate, | |
258 kOpusDefaultMaxPlaybackRate); | |
259 *max_ptime_ms = | |
260 GetCodecFeatureInt(codec, kCodecParamMaxPTime, kOpusDefaultMaxPTime); | |
261 *min_ptime_ms = | |
262 GetCodecFeatureInt(codec, kCodecParamMinPTime, kOpusDefaultMinPTime); | |
263 if (*max_ptime_ms < *min_ptime_ms) { | |
264 // If min ptime or max ptime defined by codec parameter is wrong, we use | |
265 // the default values. | |
266 *max_ptime_ms = kOpusDefaultMaxPTime; | |
267 *min_ptime_ms = kOpusDefaultMinPTime; | |
268 } | |
269 | |
270 // If OPUS, change what we send according to the "stereo" codec | |
271 // parameter, and not the "channels" parameter. We set | |
272 // voe_codec.channels to 2 if "stereo=1" and 1 otherwise. If | |
273 // the bitrate is not specified, i.e. is <= zero, we set it to the | |
274 // appropriate default value for mono or stereo Opus. | |
275 voe_codec->channels = IsCodecFeatureEnabled(codec, kCodecParamStereo) ? 2 : 1; | |
276 voe_codec->rate = GetOpusBitrate(codec, *max_playback_rate); | |
277 } | |
278 | |
279 webrtc::AudioState::Config MakeAudioStateConfig( | 182 webrtc::AudioState::Config MakeAudioStateConfig( |
280 VoEWrapper* voe_wrapper, | 183 VoEWrapper* voe_wrapper, |
281 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer) { | 184 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer) { |
282 webrtc::AudioState::Config config; | 185 webrtc::AudioState::Config config; |
283 config.voice_engine = voe_wrapper->engine(); | 186 config.voice_engine = voe_wrapper->engine(); |
284 if (audio_mixer) { | 187 if (audio_mixer) { |
285 config.audio_mixer = audio_mixer; | 188 config.audio_mixer = audio_mixer; |
286 } else { | 189 } else { |
287 config.audio_mixer = webrtc::AudioMixerImpl::Create(); | 190 config.audio_mixer = webrtc::AudioMixerImpl::Create(); |
288 } | 191 } |
289 return config; | 192 return config; |
290 } | 193 } |
291 | 194 |
292 class WebRtcVoiceCodecs final { | 195 class WebRtcVoiceCodecs final { |
293 public: | 196 public: |
294 // TODO(solenberg): Do this filtering once off-line, add a simple AudioCodec | 197 static bool ToCodecInst(const AudioCodec& in, webrtc::CodecInst* out) { |
ossu
2017/02/21 11:04:14
With the cleanup of a couple of more tests, this o
| |
295 // list and add a test which verifies VoE supports the listed codecs. | |
296 static std::vector<AudioCodec> SupportedSendCodecs() { | |
297 std::vector<AudioCodec> result; | |
298 // Iterate first over our preferred codecs list, so that the results are | |
299 // added in order of preference. | |
300 for (size_t i = 0; i < arraysize(kCodecPrefs); ++i) { | |
301 const CodecPref* pref = &kCodecPrefs[i]; | |
302 for (webrtc::CodecInst voe_codec : webrtc::acm2::RentACodec::Database()) { | |
303 // Change the sample rate of G722 to 8000 to match SDP. | |
304 MaybeFixupG722(&voe_codec, 8000); | |
305 // Skip uncompressed formats. | |
306 if (IsCodec(voe_codec, kL16CodecName)) { | |
307 continue; | |
308 } | |
309 | |
310 if (!IsCodec(voe_codec, pref->name) || | |
311 pref->clockrate != voe_codec.plfreq || | |
312 pref->channels != voe_codec.channels) { | |
313 // Not a match. | |
314 continue; | |
315 } | |
316 | |
317 AudioCodec codec(pref->payload_type, voe_codec.plname, voe_codec.plfreq, | |
318 voe_codec.rate, voe_codec.channels); | |
319 LOG(LS_INFO) << "Adding supported codec: " << ToString(codec); | |
320 if (IsCodec(codec, kIsacCodecName)) { | |
321 // Indicate auto-bitrate in signaling. | |
322 codec.bitrate = 0; | |
323 } | |
324 if (IsCodec(codec, kOpusCodecName)) { | |
325 // Only add fmtp parameters that differ from the spec. | |
326 if (kPreferredMinPTime != kOpusDefaultMinPTime) { | |
327 codec.params[kCodecParamMinPTime] = | |
328 rtc::ToString(kPreferredMinPTime); | |
329 } | |
330 if (kPreferredMaxPTime != kOpusDefaultMaxPTime) { | |
331 codec.params[kCodecParamMaxPTime] = | |
332 rtc::ToString(kPreferredMaxPTime); | |
333 } | |
334 codec.SetParam(kCodecParamUseInbandFec, 1); | |
335 codec.AddFeedbackParam( | |
336 FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty)); | |
337 | |
338 // TODO(hellner): Add ptime, sprop-stereo, and stereo | |
339 // when they can be set to values other than the default. | |
340 } | |
341 result.push_back(codec); | |
342 } | |
343 } | |
344 return result; | |
345 } | |
346 | |
347 static bool ToCodecInst(const AudioCodec& in, | |
348 webrtc::CodecInst* out) { | |
349 for (webrtc::CodecInst voe_codec : webrtc::acm2::RentACodec::Database()) { | 198 for (webrtc::CodecInst voe_codec : webrtc::acm2::RentACodec::Database()) { |
350 // Change the sample rate of G722 to 8000 to match SDP. | 199 // Change the sample rate of G722 to 8000 to match SDP. |
351 MaybeFixupG722(&voe_codec, 8000); | 200 MaybeFixupG722(&voe_codec, 8000); |
352 AudioCodec codec(voe_codec.pltype, voe_codec.plname, voe_codec.plfreq, | 201 AudioCodec codec(voe_codec.pltype, voe_codec.plname, voe_codec.plfreq, |
353 voe_codec.rate, voe_codec.channels); | 202 voe_codec.rate, voe_codec.channels); |
354 bool multi_rate = IsCodecMultiRate(voe_codec); | 203 const bool multi_rate = |
204 IsCodec(codec, kIsacCodecName) || IsCodec(codec, kOpusCodecName); | |
355 // Allow arbitrary rates for ISAC to be specified. | 205 // Allow arbitrary rates for ISAC to be specified. |
356 if (multi_rate) { | 206 if (multi_rate) { |
357 // Set codec.bitrate to 0 so the check for codec.Matches() passes. | 207 // Set codec.bitrate to 0 so the check for codec.Matches() passes. |
358 codec.bitrate = 0; | 208 codec.bitrate = 0; |
359 } | 209 } |
360 if (codec.Matches(in)) { | 210 if (codec.Matches(in)) { |
361 if (out) { | 211 if (out) { |
362 // Fixup the payload type. | 212 // Fixup the payload type. |
363 voe_codec.pltype = in.id; | 213 voe_codec.pltype = in.id; |
364 | 214 |
365 // Set bitrate if specified. | 215 // Set bitrate if specified. |
366 if (multi_rate && in.bitrate != 0) { | 216 if (multi_rate && in.bitrate != 0) { |
367 voe_codec.rate = in.bitrate; | 217 voe_codec.rate = in.bitrate; |
368 } | 218 } |
369 | 219 |
370 // Reset G722 sample rate to 16000 to match WebRTC. | 220 // Reset G722 sample rate to 16000 to match WebRTC. |
371 MaybeFixupG722(&voe_codec, 16000); | 221 MaybeFixupG722(&voe_codec, 16000); |
372 | 222 |
373 *out = voe_codec; | 223 *out = voe_codec; |
374 } | 224 } |
375 return true; | 225 return true; |
376 } | 226 } |
377 } | 227 } |
378 return false; | 228 return false; |
379 } | 229 } |
380 | 230 |
381 static bool IsCodecMultiRate(const webrtc::CodecInst& codec) { | |
382 for (size_t i = 0; i < arraysize(kCodecPrefs); ++i) { | |
383 if (IsCodec(codec, kCodecPrefs[i].name) && | |
384 kCodecPrefs[i].clockrate == codec.plfreq) { | |
385 return kCodecPrefs[i].is_multi_rate; | |
386 } | |
387 } | |
388 return false; | |
389 } | |
390 | |
391 static int MaxBitrateBps(const webrtc::CodecInst& codec) { | |
392 for (size_t i = 0; i < arraysize(kCodecPrefs); ++i) { | |
393 if (IsCodec(codec, kCodecPrefs[i].name) && | |
394 kCodecPrefs[i].clockrate == codec.plfreq) { | |
395 return kCodecPrefs[i].max_bitrate_bps; | |
396 } | |
397 } | |
398 return 0; | |
399 } | |
400 | |
401 static rtc::ArrayView<const int> GetPacketSizesMs( | |
402 const webrtc::CodecInst& codec) { | |
403 for (size_t i = 0; i < arraysize(kCodecPrefs); ++i) { | |
404 if (IsCodec(codec, kCodecPrefs[i].name)) { | |
405 size_t num_packet_sizes = kMaxNumPacketSize; | |
406 for (int index = 0; index < kMaxNumPacketSize; index++) { | |
407 if (kCodecPrefs[i].packet_sizes_ms[index] == 0) { | |
408 num_packet_sizes = index; | |
409 break; | |
410 } | |
411 } | |
412 return rtc::ArrayView<const int>(kCodecPrefs[i].packet_sizes_ms, | |
413 num_packet_sizes); | |
414 } | |
415 } | |
416 return rtc::ArrayView<const int>(); | |
417 } | |
418 | |
419 // If the AudioCodec param kCodecParamPTime is set, then we will set it to | |
420 // codec pacsize if it's valid, or we will pick the next smallest value we | |
421 // support. | |
422 // TODO(Brave): Query supported packet sizes from ACM when the API is ready. | |
423 static bool SetPTimeAsPacketSize(webrtc::CodecInst* codec, int ptime_ms) { | |
424 for (const CodecPref& codec_pref : kCodecPrefs) { | |
425 if ((IsCodec(*codec, codec_pref.name) && | |
426 codec_pref.clockrate == codec->plfreq) || | |
427 IsCodec(*codec, kG722CodecName)) { | |
428 int packet_size_ms = SelectPacketSize(codec_pref, ptime_ms); | |
429 if (packet_size_ms) { | |
430 // Convert unit from milli-seconds to samples. | |
431 codec->pacsize = (codec->plfreq / 1000) * packet_size_ms; | |
432 return true; | |
433 } | |
434 } | |
435 } | |
436 return false; | |
437 } | |
438 | |
439 static const AudioCodec* GetPreferredCodec( | |
440 const std::vector<AudioCodec>& codecs, | |
441 webrtc::CodecInst* out) { | |
442 RTC_DCHECK(out); | |
443 // Select the preferred send codec (the first non-telephone-event/CN codec). | |
444 for (const AudioCodec& codec : codecs) { | |
445 if (IsCodec(codec, kDtmfCodecName) || IsCodec(codec, kCnCodecName)) { | |
446 // Skip telephone-event/CN codecs - they will be handled later. | |
447 continue; | |
448 } | |
449 | |
450 // We'll use the first codec in the list to actually send audio data. | |
451 // Be sure to use the payload type requested by the remote side. | |
452 // Ignore codecs we don't know about. The negotiation step should prevent | |
453 // this, but double-check to be sure. | |
454 if (!ToCodecInst(codec, out)) { | |
455 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); | |
456 continue; | |
457 } | |
458 return &codec; | |
459 } | |
460 return nullptr; | |
461 } | |
462 | |
463 private: | |
464 static const int kMaxNumPacketSize = 6; | |
465 struct CodecPref { | |
466 const char* name; | |
467 int clockrate; | |
468 size_t channels; | |
469 int payload_type; | |
470 bool is_multi_rate; | |
471 int packet_sizes_ms[kMaxNumPacketSize]; | |
472 int max_bitrate_bps; | |
473 }; | |
474 // Note: keep the supported packet sizes in ascending order. | |
475 static const CodecPref kCodecPrefs[14]; | |
476 | |
477 static int SelectPacketSize(const CodecPref& codec_pref, int ptime_ms) { | |
478 int selected_packet_size_ms = codec_pref.packet_sizes_ms[0]; | |
479 for (int packet_size_ms : codec_pref.packet_sizes_ms) { | |
480 if (packet_size_ms && packet_size_ms <= ptime_ms) { | |
481 selected_packet_size_ms = packet_size_ms; | |
482 } | |
483 } | |
484 return selected_packet_size_ms; | |
485 } | |
486 | |
487 // Changes RTP timestamp rate of G722. This is due to the "bug" in the RFC | 231 // Changes RTP timestamp rate of G722. This is due to the "bug" in the RFC |
488 // which says that G722 should be advertised as 8 kHz although it is a 16 kHz | 232 // which says that G722 should be advertised as 8 kHz although it is a 16 kHz |
489 // codec. | 233 // codec. |
490 static void MaybeFixupG722(webrtc::CodecInst* voe_codec, int new_plfreq) { | 234 static void MaybeFixupG722(webrtc::CodecInst* voe_codec, int new_plfreq) { |
491 if (IsCodec(*voe_codec, kG722CodecName)) { | 235 if (IsCodec(*voe_codec, kG722CodecName)) { |
492 // If the DCHECK triggers, the codec definition in WebRTC VoiceEngine | 236 // If the DCHECK triggers, the codec definition in WebRTC VoiceEngine |
493 // has changed, and this special case is no longer needed. | 237 // has changed, and this special case is no longer needed. |
494 RTC_DCHECK(voe_codec->plfreq != new_plfreq); | 238 RTC_DCHECK(voe_codec->plfreq != new_plfreq); |
495 voe_codec->plfreq = new_plfreq; | 239 voe_codec->plfreq = new_plfreq; |
496 } | 240 } |
497 } | 241 } |
498 }; | 242 }; |
499 | 243 |
500 const WebRtcVoiceCodecs::CodecPref WebRtcVoiceCodecs::kCodecPrefs[14] = { | |
501 #if WEBRTC_OPUS_SUPPORT_120MS_PTIME | |
502 {kOpusCodecName, 48000, 2, 111, true, {10, 20, 40, 60, 120}, | |
503 kOpusMaxBitrateBps}, | |
504 #else | |
505 {kOpusCodecName, 48000, 2, 111, true, {10, 20, 40, 60}, kOpusMaxBitrateBps}, | |
506 #endif | |
507 {kIsacCodecName, 16000, 1, 103, true, {30, 60}, kIsacMaxBitrateBps}, | |
508 {kIsacCodecName, 32000, 1, 104, true, {30}, kIsacMaxBitrateBps}, | |
509 // G722 should be advertised as 8000 Hz because of the RFC "bug". | |
510 {kG722CodecName, 8000, 1, 9, false, {10, 20, 30, 40, 50, 60}}, | |
511 {kIlbcCodecName, 8000, 1, 102, false, {20, 30, 40, 60}}, | |
512 {kPcmuCodecName, 8000, 1, 0, false, {10, 20, 30, 40, 50, 60}}, | |
513 {kPcmaCodecName, 8000, 1, 8, false, {10, 20, 30, 40, 50, 60}}, | |
514 {kCnCodecName, 32000, 1, 106, false, {}}, | |
515 {kCnCodecName, 16000, 1, 105, false, {}}, | |
516 {kCnCodecName, 8000, 1, 13, false, {}}, | |
517 {kDtmfCodecName, 48000, 1, 110, false, {}}, | |
518 {kDtmfCodecName, 32000, 1, 112, false, {}}, | |
519 {kDtmfCodecName, 16000, 1, 113, false, {}}, | |
520 {kDtmfCodecName, 8000, 1, 126, false, {}} | |
521 }; | |
522 | |
523 // |max_send_bitrate_bps| is the bitrate from "b=" in SDP. | 244 // |max_send_bitrate_bps| is the bitrate from "b=" in SDP. |
524 // |rtp_max_bitrate_bps| is the bitrate from RtpSender::SetParameters. | 245 // |rtp_max_bitrate_bps| is the bitrate from RtpSender::SetParameters. |
525 rtc::Optional<int> ComputeSendBitrate(int max_send_bitrate_bps, | 246 rtc::Optional<int> ComputeSendBitrate(int max_send_bitrate_bps, |
526 rtc::Optional<int> rtp_max_bitrate_bps, | 247 rtc::Optional<int> rtp_max_bitrate_bps, |
527 const webrtc::CodecInst& codec_inst) { | 248 const webrtc::AudioCodecSpec& spec) { |
528 // If application-configured bitrate is set, take minimum of that and SDP | 249 // If application-configured bitrate is set, take minimum of that and SDP |
529 // bitrate. | 250 // bitrate. |
530 const int bps = rtp_max_bitrate_bps | 251 const int bps = rtp_max_bitrate_bps |
531 ? MinPositive(max_send_bitrate_bps, *rtp_max_bitrate_bps) | 252 ? MinPositive(max_send_bitrate_bps, *rtp_max_bitrate_bps) |
532 : max_send_bitrate_bps; | 253 : max_send_bitrate_bps; |
533 const int codec_rate = codec_inst.rate; | |
534 | |
535 if (bps <= 0) { | 254 if (bps <= 0) { |
536 return rtc::Optional<int>(codec_rate); | 255 return rtc::Optional<int>(spec.info.default_bitrate_bps); |
537 } | 256 } |
538 | 257 |
539 if (codec_inst.pltype == -1) { | 258 // TODO(ossu): ???? |
ossu
2017/02/21 11:04:14
I ... don't know why this early-out was here befor
| |
540 return rtc::Optional<int>(codec_rate); | 259 // if (codec_inst.pltype == -1) { |
541 ; | 260 // return rtc::Optional<int>(codec_rate); |
542 } | 261 // } |
543 | 262 |
544 if (WebRtcVoiceCodecs::IsCodecMultiRate(codec_inst)) { | 263 if (bps < spec.info.min_bitrate_bps) { |
545 // If codec is multi-rate then just set the bitrate. | |
546 return rtc::Optional<int>( | |
547 std::min(bps, WebRtcVoiceCodecs::MaxBitrateBps(codec_inst))); | |
548 } | |
549 | |
550 if (bps < codec_inst.rate) { | |
551 // If codec is not multi-rate and |bps| is less than the fixed bitrate then | 264 // If codec is not multi-rate and |bps| is less than the fixed bitrate then |
552 // fail. If codec is not multi-rate and |bps| exceeds or equal the fixed | 265 // fail. If codec is not multi-rate and |bps| exceeds or equal the fixed |
553 // bitrate then ignore. | 266 // bitrate then ignore. |
kwiberg-webrtc
2017/02/21 23:35:03
This comment doesn't seem entirely accurate. And i
| |
554 LOG(LS_ERROR) << "Failed to set codec " << codec_inst.plname | 267 LOG(LS_ERROR) << "Failed to set codec " << spec.format.name |
555 << " to bitrate " << bps << " bps" | 268 << " to bitrate " << bps << " bps" |
556 << ", requires at least " << codec_inst.rate << " bps."; | 269 << ", requires at least " << spec.info.min_bitrate_bps |
270 << " bps."; | |
557 return rtc::Optional<int>(); | 271 return rtc::Optional<int>(); |
558 } | 272 } |
559 return rtc::Optional<int>(codec_rate); | 273 |
274 if (spec.info.HasFixedBitrate()) { | |
275 return rtc::Optional<int>(spec.info.default_bitrate_bps); | |
276 } else { | |
277 // If codec is multi-rate then just set the bitrate. | |
278 return rtc::Optional<int>(std::min(bps, spec.info.max_bitrate_bps)); | |
279 } | |
560 } | 280 } |
561 | 281 |
562 } // namespace { | 282 } // namespace |
563 | 283 |
564 bool WebRtcVoiceEngine::ToCodecInst(const AudioCodec& in, | 284 bool WebRtcVoiceEngine::ToCodecInst(const AudioCodec& in, |
565 webrtc::CodecInst* out) { | 285 webrtc::CodecInst* out) { |
566 return WebRtcVoiceCodecs::ToCodecInst(in, out); | 286 return WebRtcVoiceCodecs::ToCodecInst(in, out); |
567 } | 287 } |
568 | 288 |
569 WebRtcVoiceEngine::WebRtcVoiceEngine( | 289 WebRtcVoiceEngine::WebRtcVoiceEngine( |
570 webrtc::AudioDeviceModule* adm, | 290 webrtc::AudioDeviceModule* adm, |
571 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory, | 291 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory, |
572 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer) | 292 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer) |
573 : WebRtcVoiceEngine(adm, decoder_factory, audio_mixer, new VoEWrapper()) { | 293 : WebRtcVoiceEngine(adm, decoder_factory, audio_mixer, new VoEWrapper()) { |
574 audio_state_ = | 294 audio_state_ = |
575 webrtc::AudioState::Create(MakeAudioStateConfig(voe(), audio_mixer)); | 295 webrtc::AudioState::Create(MakeAudioStateConfig(voe(), audio_mixer)); |
576 } | 296 } |
577 | 297 |
578 WebRtcVoiceEngine::WebRtcVoiceEngine( | 298 WebRtcVoiceEngine::WebRtcVoiceEngine( |
579 webrtc::AudioDeviceModule* adm, | 299 webrtc::AudioDeviceModule* adm, |
580 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory, | 300 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory, |
581 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer, | 301 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer, |
582 VoEWrapper* voe_wrapper) | 302 VoEWrapper* voe_wrapper) |
583 : adm_(adm), decoder_factory_(decoder_factory), voe_wrapper_(voe_wrapper) { | 303 : adm_(adm), |
304 encoder_factory_(webrtc::CreateBuiltinAudioEncoderFactory()), | |
305 decoder_factory_(decoder_factory), | |
306 voe_wrapper_(voe_wrapper) { | |
584 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 307 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
585 LOG(LS_INFO) << "WebRtcVoiceEngine::WebRtcVoiceEngine"; | 308 LOG(LS_INFO) << "WebRtcVoiceEngine::WebRtcVoiceEngine"; |
586 RTC_DCHECK(voe_wrapper); | 309 RTC_DCHECK(voe_wrapper); |
587 RTC_DCHECK(decoder_factory); | 310 RTC_DCHECK(decoder_factory); |
588 | 311 |
589 signal_thread_checker_.DetachFromThread(); | 312 signal_thread_checker_.DetachFromThread(); |
590 | 313 |
591 // Load our audio codec list. | 314 // Load our audio codec list. |
592 LOG(LS_INFO) << "Supported send codecs in order of preference:"; | 315 LOG(LS_INFO) << "Supported send codecs in order of preference:"; |
593 send_codecs_ = WebRtcVoiceCodecs::SupportedSendCodecs(); | 316 send_codecs_ = CollectCodecs(encoder_factory_->GetSupportedEncoders()); |
594 for (const AudioCodec& codec : send_codecs_) { | 317 for (const AudioCodec& codec : send_codecs_) { |
595 LOG(LS_INFO) << ToString(codec); | 318 LOG(LS_INFO) << ToString(codec); |
596 } | 319 } |
597 | 320 |
598 LOG(LS_INFO) << "Supported recv codecs in order of preference:"; | 321 LOG(LS_INFO) << "Supported recv codecs in order of preference:"; |
599 recv_codecs_ = CollectRecvCodecs(); | 322 recv_codecs_ = CollectCodecs(decoder_factory_->GetSupportedDecoders()); |
600 for (const AudioCodec& codec : recv_codecs_) { | 323 for (const AudioCodec& codec : recv_codecs_) { |
601 LOG(LS_INFO) << ToString(codec); | 324 LOG(LS_INFO) << ToString(codec); |
602 } | 325 } |
603 | 326 |
604 channel_config_.enable_voice_pacing = true; | 327 channel_config_.enable_voice_pacing = true; |
605 | 328 |
606 // Temporarily turn logging level up for the Init() call. | 329 // Temporarily turn logging level up for the Init() call. |
607 webrtc::Trace::SetTraceCallback(this); | 330 webrtc::Trace::SetTraceCallback(this); |
608 webrtc::Trace::set_level_filter(kElevatedTraceFilter); | 331 webrtc::Trace::set_level_filter(kElevatedTraceFilter); |
609 LOG(LS_INFO) << webrtc::VoiceEngine::GetVersionString(); | 332 LOG(LS_INFO) << webrtc::VoiceEngine::GetVersionString(); |
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1141 RTC_DCHECK(adm_); | 864 RTC_DCHECK(adm_); |
1142 return adm_; | 865 return adm_; |
1143 } | 866 } |
1144 | 867 |
1145 webrtc::AudioProcessing* WebRtcVoiceEngine::apm() { | 868 webrtc::AudioProcessing* WebRtcVoiceEngine::apm() { |
1146 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 869 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
1147 RTC_DCHECK(apm_); | 870 RTC_DCHECK(apm_); |
1148 return apm_; | 871 return apm_; |
1149 } | 872 } |
1150 | 873 |
1151 AudioCodecs WebRtcVoiceEngine::CollectRecvCodecs() const { | 874 AudioCodecs WebRtcVoiceEngine::CollectCodecs( |
875 const std::vector<webrtc::AudioCodecSpec>& specs) const { | |
1152 PayloadTypeMapper mapper; | 876 PayloadTypeMapper mapper; |
1153 AudioCodecs out; | 877 AudioCodecs out; |
1154 const std::vector<webrtc::AudioCodecSpec>& specs = | |
1155 decoder_factory_->GetSupportedDecoders(); | |
1156 | 878 |
1157 // Only generate CN payload types for these clockrates: | 879 // Only generate CN payload types for these clockrates: |
1158 std::map<int, bool, std::greater<int>> generate_cn = {{ 8000, false }, | 880 std::map<int, bool, std::greater<int>> generate_cn = {{ 8000, false }, |
1159 { 16000, false }, | 881 { 16000, false }, |
1160 { 32000, false }}; | 882 { 32000, false }}; |
1161 // Only generate telephone-event payload types for these clockrates: | 883 // Only generate telephone-event payload types for these clockrates: |
1162 std::map<int, bool, std::greater<int>> generate_dtmf = {{ 8000, false }, | 884 std::map<int, bool, std::greater<int>> generate_dtmf = {{ 8000, false }, |
1163 { 16000, false }, | 885 { 16000, false }, |
1164 { 32000, false }, | 886 { 32000, false }, |
1165 { 48000, false }}; | 887 { 48000, false }}; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1230 WebRtcAudioSendStream( | 952 WebRtcAudioSendStream( |
1231 int ch, | 953 int ch, |
1232 webrtc::AudioTransport* voe_audio_transport, | 954 webrtc::AudioTransport* voe_audio_transport, |
1233 uint32_t ssrc, | 955 uint32_t ssrc, |
1234 const std::string& c_name, | 956 const std::string& c_name, |
1235 const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec, | 957 const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec, |
1236 const std::vector<webrtc::RtpExtension>& extensions, | 958 const std::vector<webrtc::RtpExtension>& extensions, |
1237 int max_send_bitrate_bps, | 959 int max_send_bitrate_bps, |
1238 const rtc::Optional<std::string>& audio_network_adaptor_config, | 960 const rtc::Optional<std::string>& audio_network_adaptor_config, |
1239 webrtc::Call* call, | 961 webrtc::Call* call, |
1240 webrtc::Transport* send_transport) | 962 webrtc::Transport* send_transport, |
963 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory) | |
1241 : voe_audio_transport_(voe_audio_transport), | 964 : voe_audio_transport_(voe_audio_transport), |
1242 call_(call), | 965 call_(call), |
1243 config_(send_transport), | 966 config_(send_transport), |
1244 send_side_bwe_with_overhead_(webrtc::field_trial::FindFullName( | 967 send_side_bwe_with_overhead_(webrtc::field_trial::FindFullName( |
1245 "WebRTC-SendSideBwe-WithOverhead") == "Enabled"), | 968 "WebRTC-SendSideBwe-WithOverhead") == "Enabled"), |
1246 max_send_bitrate_bps_(max_send_bitrate_bps), | 969 max_send_bitrate_bps_(max_send_bitrate_bps), |
1247 rtp_parameters_(CreateRtpParametersWithOneEncoding()) { | 970 rtp_parameters_(CreateRtpParametersWithOneEncoding()) { |
1248 RTC_DCHECK_GE(ch, 0); | 971 RTC_DCHECK_GE(ch, 0); |
1249 // TODO(solenberg): Once we're not using FakeWebRtcVoiceEngine anymore: | 972 // TODO(solenberg): Once we're not using FakeWebRtcVoiceEngine anymore: |
1250 // RTC_DCHECK(voe_audio_transport); | 973 // RTC_DCHECK(voe_audio_transport); |
1251 RTC_DCHECK(call); | 974 RTC_DCHECK(call); |
975 RTC_DCHECK(encoder_factory); | |
1252 config_.rtp.ssrc = ssrc; | 976 config_.rtp.ssrc = ssrc; |
1253 config_.rtp.c_name = c_name; | 977 config_.rtp.c_name = c_name; |
1254 config_.voe_channel_id = ch; | 978 config_.voe_channel_id = ch; |
1255 config_.rtp.extensions = extensions; | 979 config_.rtp.extensions = extensions; |
1256 config_.audio_network_adaptor_config = audio_network_adaptor_config; | 980 config_.audio_network_adaptor_config = audio_network_adaptor_config; |
981 config_.encoder_factory = encoder_factory; | |
1257 rtp_parameters_.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc); | 982 rtp_parameters_.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc); |
1258 RecreateAudioSendStream(send_codec_spec); | 983 RecreateAudioSendStream(send_codec_spec); |
1259 } | 984 } |
1260 | 985 |
1261 ~WebRtcAudioSendStream() override { | 986 ~WebRtcAudioSendStream() override { |
1262 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 987 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
1263 ClearSource(); | 988 ClearSource(); |
1264 call_->DestroyAudioSendStream(stream_); | 989 call_->DestroyAudioSendStream(stream_); |
1265 } | 990 } |
1266 | 991 |
1267 void RecreateAudioSendStream( | 992 void RecreateAudioSendStream( |
1268 const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec) { | 993 const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec) { |
1269 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 994 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
1270 send_codec_spec_ = send_codec_spec; | 995 send_codec_spec_ = send_codec_spec; |
1271 config_.rtp.nack.rtp_history_ms = | 996 config_.rtp.nack.rtp_history_ms = |
1272 send_codec_spec_.nack_enabled ? kNackRtpHistoryMs : 0; | 997 send_codec_spec_.nack_enabled ? kNackRtpHistoryMs : 0; |
1273 config_.send_codec_spec = send_codec_spec_; | 998 config_.send_codec_spec = send_codec_spec_; |
1274 auto send_rate = ComputeSendBitrate( | 999 // TODO(ossu): This is strange, since we're changing our send_codec_spec, |
1000 // overwriting values we just got. | |
1001 config_.send_codec_spec.target_bitrate_bps = ComputeSendBitrate( | |
1275 max_send_bitrate_bps_, rtp_parameters_.encodings[0].max_bitrate_bps, | 1002 max_send_bitrate_bps_, rtp_parameters_.encodings[0].max_bitrate_bps, |
1276 send_codec_spec.codec_inst); | 1003 config_.send_codec_spec.format); |
1277 if (send_rate) { | |
1278 // Apply a send rate that abides by |max_send_bitrate_bps_| and | |
1279 // |rtp_parameters_| when possible. Otherwise use the codec rate. | |
1280 config_.send_codec_spec.codec_inst.rate = *send_rate; | |
1281 } | |
1282 RecreateAudioSendStream(); | 1004 RecreateAudioSendStream(); |
1283 } | 1005 } |
1284 | 1006 |
1285 void RecreateAudioSendStream( | 1007 void RecreateAudioSendStream( |
1286 const std::vector<webrtc::RtpExtension>& extensions) { | 1008 const std::vector<webrtc::RtpExtension>& extensions) { |
1287 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1009 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
1288 config_.rtp.extensions = extensions; | 1010 config_.rtp.extensions = extensions; |
1289 RecreateAudioSendStream(); | 1011 RecreateAudioSendStream(); |
1290 } | 1012 } |
1291 | 1013 |
1292 void RecreateAudioSendStream( | 1014 void RecreateAudioSendStream( |
1293 const rtc::Optional<std::string>& audio_network_adaptor_config) { | 1015 const rtc::Optional<std::string>& audio_network_adaptor_config) { |
1294 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1016 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
1295 if (config_.audio_network_adaptor_config == audio_network_adaptor_config) { | 1017 if (config_.audio_network_adaptor_config == audio_network_adaptor_config) { |
1296 return; | 1018 return; |
1297 } | 1019 } |
1298 config_.audio_network_adaptor_config = audio_network_adaptor_config; | 1020 config_.audio_network_adaptor_config = audio_network_adaptor_config; |
1299 RecreateAudioSendStream(); | 1021 RecreateAudioSendStream(); |
1300 } | 1022 } |
1301 | 1023 |
1302 bool SetMaxSendBitrate(int bps) { | 1024 bool SetMaxSendBitrate(int bps) { |
1303 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1025 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
1304 auto send_rate = | 1026 auto send_rate = |
1305 ComputeSendBitrate(bps, rtp_parameters_.encodings[0].max_bitrate_bps, | 1027 ComputeSendBitrate(bps, rtp_parameters_.encodings[0].max_bitrate_bps, |
1306 send_codec_spec_.codec_inst); | 1028 config_.send_codec_spec.format); |
1029 | |
1307 if (!send_rate) { | 1030 if (!send_rate) { |
1308 return false; | 1031 return false; |
1309 } | 1032 } |
1310 | 1033 |
1311 max_send_bitrate_bps_ = bps; | 1034 max_send_bitrate_bps_ = bps; |
1312 | 1035 |
1313 if (config_.send_codec_spec.codec_inst.rate != *send_rate) { | 1036 if (send_rate != config_.send_codec_spec.target_bitrate_bps) { |
1314 // Recreate AudioSendStream with new bit rate. | 1037 // TODO(ossu): Should not recreate stream! |
kwiberg-webrtc
2017/02/21 23:35:03
Because we should mutate the one we have?
| |
1315 config_.send_codec_spec.codec_inst.rate = *send_rate; | 1038 config_.send_codec_spec.target_bitrate_bps = send_rate; |
1316 RecreateAudioSendStream(); | 1039 RecreateAudioSendStream(); |
1317 } | 1040 } |
1318 return true; | 1041 return true; |
1319 } | 1042 } |
1320 | 1043 |
1321 bool SendTelephoneEvent(int payload_type, int payload_freq, int event, | 1044 bool SendTelephoneEvent(int payload_type, int payload_freq, int event, |
1322 int duration_ms) { | 1045 int duration_ms) { |
1323 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 1046 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
1324 RTC_DCHECK(stream_); | 1047 RTC_DCHECK(stream_); |
1325 return stream_->SendTelephoneEvent(payload_type, payload_freq, event, | 1048 return stream_->SendTelephoneEvent(payload_type, payload_freq, event, |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1424 } | 1147 } |
1425 return true; | 1148 return true; |
1426 } | 1149 } |
1427 | 1150 |
1428 bool SetRtpParameters(const webrtc::RtpParameters& parameters) { | 1151 bool SetRtpParameters(const webrtc::RtpParameters& parameters) { |
1429 if (!ValidateRtpParameters(parameters)) { | 1152 if (!ValidateRtpParameters(parameters)) { |
1430 return false; | 1153 return false; |
1431 } | 1154 } |
1432 auto send_rate = ComputeSendBitrate(max_send_bitrate_bps_, | 1155 auto send_rate = ComputeSendBitrate(max_send_bitrate_bps_, |
1433 parameters.encodings[0].max_bitrate_bps, | 1156 parameters.encodings[0].max_bitrate_bps, |
1434 send_codec_spec_.codec_inst); | 1157 config_.send_codec_spec.format); |
1435 if (!send_rate) { | 1158 if (!send_rate) { |
1436 return false; | 1159 return false; |
1437 } | 1160 } |
1438 | 1161 |
1439 rtp_parameters_ = parameters; | 1162 rtp_parameters_ = parameters; |
1440 | 1163 |
1441 // parameters.encodings[0].encodings[0].max_bitrate_bps could have changed. | 1164 // parameters.encodings[0].encodings[0].max_bitrate_bps could have changed. |
1442 if (config_.send_codec_spec.codec_inst.rate != *send_rate) { | 1165 if (send_rate != config_.send_codec_spec.target_bitrate_bps) { |
1166 // TODO(ossu): Should not recreate stream! | |
1443 // Recreate AudioSendStream with new bit rate. | 1167 // Recreate AudioSendStream with new bit rate. |
1444 config_.send_codec_spec.codec_inst.rate = *send_rate; | 1168 config_.send_codec_spec.target_bitrate_bps = send_rate; |
1445 RecreateAudioSendStream(); | 1169 RecreateAudioSendStream(); |
1446 } else { | 1170 } else { |
1447 // parameters.encodings[0].active could have changed. | 1171 // parameters.encodings[0].active could have changed. |
1448 UpdateSendState(); | 1172 UpdateSendState(); |
1449 } | 1173 } |
1450 return true; | 1174 return true; |
1451 } | 1175 } |
1452 | 1176 |
1453 private: | 1177 private: |
1454 void UpdateSendState() { | 1178 void UpdateSendState() { |
(...skipping 14 matching lines...) Expand all Loading... | |
1469 stream_ = nullptr; | 1193 stream_ = nullptr; |
1470 } | 1194 } |
1471 RTC_DCHECK(!stream_); | 1195 RTC_DCHECK(!stream_); |
1472 if (webrtc::field_trial::FindFullName("WebRTC-Audio-SendSideBwe") == | 1196 if (webrtc::field_trial::FindFullName("WebRTC-Audio-SendSideBwe") == |
1473 "Enabled") { | 1197 "Enabled") { |
1474 config_.min_bitrate_bps = kOpusMinBitrateBps; | 1198 config_.min_bitrate_bps = kOpusMinBitrateBps; |
1475 config_.max_bitrate_bps = kOpusBitrateFbBps; | 1199 config_.max_bitrate_bps = kOpusBitrateFbBps; |
1476 // TODO(mflodman): Keep testing this and set proper values. | 1200 // TODO(mflodman): Keep testing this and set proper values. |
1477 // Note: This is an early experiment currently only supported by Opus. | 1201 // Note: This is an early experiment currently only supported by Opus. |
1478 if (send_side_bwe_with_overhead_) { | 1202 if (send_side_bwe_with_overhead_) { |
1479 auto packet_sizes_ms = WebRtcVoiceCodecs::GetPacketSizesMs( | 1203 const bool is_opus_with_ana = |
1480 config_.send_codec_spec.codec_inst); | 1204 config_.audio_network_adaptor_config && |
1481 if (!packet_sizes_ms.empty()) { | 1205 !STR_CASE_CMP(config_.send_codec_spec.format.format.name.c_str(), |
1482 int max_packet_size_ms = | 1206 kOpusCodecName); |
1483 *std::max_element(packet_sizes_ms.begin(), packet_sizes_ms.end()); | 1207 const int max_packet_size_ms = |
1484 int min_packet_size_ms = | 1208 (is_opus_with_ana && WEBRTC_OPUS_SUPPORT_120MS_PTIME) ? 120 : 60; |
1485 *std::min_element(packet_sizes_ms.begin(), packet_sizes_ms.end()); | 1209 // Audio network adaptor will just use 20ms and 60ms frame lengths. |
1210 // The adaptor will only be active for the Opus encoder. | |
1211 const int min_packet_size_ms = is_opus_with_ana ? 20 : 10; | |
1486 | 1212 |
1487 // Audio network adaptor will just use 20ms and 60ms frame lengths. | 1213 // OverheadPerPacket = Ipv4(20B) + UDP(8B) + SRTP(10B) + RTP(12) |
kwiberg-webrtc
2017/02/21 23:35:03
Missing B
| |
1488 // The adaptor will only be active for the Opus encoder. | 1214 constexpr int kOverheadPerPacket = 20 + 8 + 10 + 12; |
1489 if (config_.audio_network_adaptor_config && | |
1490 IsCodec(config_.send_codec_spec.codec_inst, kOpusCodecName)) { | |
1491 #if WEBRTC_OPUS_SUPPORT_120MS_PTIME | |
1492 max_packet_size_ms = 120; | |
1493 #else | |
1494 max_packet_size_ms = 60; | |
1495 #endif | |
1496 min_packet_size_ms = 20; | |
1497 } | |
1498 | 1215 |
1499 // OverheadPerPacket = Ipv4(20B) + UDP(8B) + SRTP(10B) + RTP(12) | 1216 int min_overhead_bps = |
1500 constexpr int kOverheadPerPacket = 20 + 8 + 10 + 12; | 1217 kOverheadPerPacket * 8 * 1000 / max_packet_size_ms; |
1501 | 1218 |
1502 int min_overhead_bps = | 1219 int max_overhead_bps = |
1503 kOverheadPerPacket * 8 * 1000 / max_packet_size_ms; | 1220 kOverheadPerPacket * 8 * 1000 / min_packet_size_ms; |
1504 | 1221 |
1505 int max_overhead_bps = | 1222 config_.min_bitrate_bps = kOpusMinBitrateBps + min_overhead_bps; |
1506 kOverheadPerPacket * 8 * 1000 / min_packet_size_ms; | 1223 config_.max_bitrate_bps = kOpusBitrateFbBps + max_overhead_bps; |
1507 | |
1508 config_.min_bitrate_bps = kOpusMinBitrateBps + min_overhead_bps; | |
1509 config_.max_bitrate_bps = kOpusBitrateFbBps + max_overhead_bps; | |
1510 } | |
1511 } | 1224 } |
1512 } | 1225 } |
1513 stream_ = call_->CreateAudioSendStream(config_); | 1226 stream_ = call_->CreateAudioSendStream(config_); |
1514 RTC_CHECK(stream_); | 1227 RTC_CHECK(stream_); |
1515 UpdateSendState(); | 1228 UpdateSendState(); |
1516 } | 1229 } |
1517 | 1230 |
1518 rtc::ThreadChecker worker_thread_checker_; | 1231 rtc::ThreadChecker worker_thread_checker_; |
1519 rtc::RaceChecker audio_capture_race_checker_; | 1232 rtc::RaceChecker audio_capture_race_checker_; |
1520 webrtc::AudioTransport* const voe_audio_transport_ = nullptr; | 1233 webrtc::AudioTransport* const voe_audio_transport_ = nullptr; |
1521 webrtc::Call* call_ = nullptr; | 1234 webrtc::Call* call_ = nullptr; |
1522 webrtc::AudioSendStream::Config config_; | 1235 webrtc::AudioSendStream::Config config_; |
1523 const bool send_side_bwe_with_overhead_; | 1236 const bool send_side_bwe_with_overhead_; |
1524 // The stream is owned by WebRtcAudioSendStream and may be reallocated if | 1237 // The stream is owned by WebRtcAudioSendStream and may be reallocated if |
1525 // configuration changes. | 1238 // configuration changes. |
1526 webrtc::AudioSendStream* stream_ = nullptr; | 1239 webrtc::AudioSendStream* stream_ = nullptr; |
1527 | 1240 |
1528 // Raw pointer to AudioSource owned by LocalAudioTrackHandler. | 1241 // Raw pointer to AudioSource owned by LocalAudioTrackHandler. |
1529 // PeerConnection will make sure invalidating the pointer before the object | 1242 // PeerConnection will make sure invalidating the pointer before the object |
1530 // goes away. | 1243 // goes away. |
1531 AudioSource* source_ = nullptr; | 1244 AudioSource* source_ = nullptr; |
1532 bool send_ = false; | 1245 bool send_ = false; |
1533 bool muted_ = false; | 1246 bool muted_ = false; |
1534 int max_send_bitrate_bps_; | 1247 int max_send_bitrate_bps_; |
1535 webrtc::RtpParameters rtp_parameters_; | 1248 webrtc::RtpParameters rtp_parameters_; |
1536 webrtc::AudioSendStream::Config::SendCodecSpec send_codec_spec_; | 1249 webrtc::AudioSendStream::Config::SendCodecSpec send_codec_spec_; |
1250 webrtc::AudioFormatInfo audio_format_info_; | |
ossu
2017/02/21 11:04:14
Not used. Will remove.
| |
1537 | 1251 |
1538 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream); | 1252 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream); |
1539 }; | 1253 }; |
1540 | 1254 |
1541 class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { | 1255 class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { |
1542 public: | 1256 public: |
1543 WebRtcAudioReceiveStream( | 1257 WebRtcAudioReceiveStream( |
1544 int ch, | 1258 int ch, |
1545 uint32_t remote_ssrc, | 1259 uint32_t remote_ssrc, |
1546 uint32_t local_ssrc, | 1260 uint32_t local_ssrc, |
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1983 } | 1697 } |
1984 | 1698 |
1985 // Scan through the list to figure out the codec to use for sending, along | 1699 // Scan through the list to figure out the codec to use for sending, along |
1986 // with the proper configuration for VAD, CNG, NACK and Opus-specific | 1700 // with the proper configuration for VAD, CNG, NACK and Opus-specific |
1987 // parameters. | 1701 // parameters. |
1988 // TODO(solenberg): Refactor this logic once we create AudioEncoders here. | 1702 // TODO(solenberg): Refactor this logic once we create AudioEncoders here. |
1989 webrtc::AudioSendStream::Config::SendCodecSpec send_codec_spec; | 1703 webrtc::AudioSendStream::Config::SendCodecSpec send_codec_spec; |
1990 { | 1704 { |
1991 send_codec_spec.nack_enabled = send_codec_spec_.nack_enabled; | 1705 send_codec_spec.nack_enabled = send_codec_spec_.nack_enabled; |
1992 | 1706 |
1993 // Find send codec (the first non-telephone-event/CN codec). | 1707 const AudioCodec* chosen_codec = nullptr; |
1994 const AudioCodec* codec = WebRtcVoiceCodecs::GetPreferredCodec( | 1708 for (const auto& codec : codecs) { |
1995 codecs, &send_codec_spec.codec_inst); | 1709 if (!(IsCodec(codec, kCnCodecName) || |
1996 if (!codec) { | 1710 IsCodec(codec, kDtmfCodecName) || |
1997 LOG(LS_WARNING) << "Received empty list of codecs."; | 1711 IsCodec(codec, kRedCodecName))) { |
kwiberg-webrtc
2017/02/21 23:35:03
To reduce indentation, invert this condition and "
| |
1998 return false; | 1712 webrtc::SdpAudioFormat format(codec.name, codec.clockrate, |
1713 codec.channels, | |
1714 CodecParameterMap(codec.params)); | |
1715 | |
1716 auto info = engine()->encoder_factory_->QueryAudioFormat(format); | |
kwiberg-webrtc
2017/02/21 23:35:03
It may be useful to write out this type.
| |
1717 // Ignore codecs we don't know about. The negotiation step should | |
1718 // prevent this, but double-check to be sure. | |
1719 if (!info) { | |
1720 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); | |
1721 continue; | |
1722 } | |
1723 | |
1724 // If a bitrate has been specified for the codec, use it over the | |
1725 // codec's default. | |
1726 if (codec.bitrate > 0) { | |
1727 info->default_bitrate_bps = | |
1728 std::max(info->min_bitrate_bps, | |
1729 std::min(info->max_bitrate_bps, codec.bitrate)); | |
1730 } | |
1731 | |
1732 chosen_codec = &codec; | |
1733 send_codec_spec.payload_type = chosen_codec->id; | |
1734 send_codec_spec.format.format = format; | |
1735 send_codec_spec.format.info = *info; | |
1736 send_codec_spec.transport_cc_enabled = HasTransportCc(*chosen_codec); | |
1737 send_codec_spec.nack_enabled = HasNack(*chosen_codec); | |
1738 bitrate_config_ = GetBitrateConfigForCodec(*chosen_codec); | |
1739 break; | |
1740 } | |
1999 } | 1741 } |
2000 | 1742 |
2001 send_codec_spec.transport_cc_enabled = HasTransportCc(*codec); | 1743 if (!chosen_codec) |
2002 send_codec_spec.nack_enabled = HasNack(*codec); | 1744 return false; |
2003 bitrate_config_ = GetBitrateConfigForCodec(*codec); | |
2004 | 1745 |
2005 // For Opus as the send codec, we are to determine inband FEC, maximum | |
2006 // playback rate, and opus internal dtx. | |
2007 if (IsCodec(*codec, kOpusCodecName)) { | |
2008 GetOpusConfig(*codec, &send_codec_spec.codec_inst, | |
2009 &send_codec_spec.enable_codec_fec, | |
2010 &send_codec_spec.opus_max_playback_rate, | |
2011 &send_codec_spec.enable_opus_dtx, | |
2012 &send_codec_spec.min_ptime_ms, | |
2013 &send_codec_spec.max_ptime_ms); | |
2014 } | |
2015 | |
2016 // Set packet size if the AudioCodec param kCodecParamPTime is set. | |
2017 int ptime_ms = 0; | |
2018 if (codec->GetParam(kCodecParamPTime, &ptime_ms)) { | |
2019 if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize( | |
2020 &send_codec_spec.codec_inst, ptime_ms)) { | |
2021 LOG(LS_WARNING) << "Failed to set packet size for codec " | |
2022 << send_codec_spec.codec_inst.plname; | |
2023 return false; | |
2024 } | |
2025 } | |
2026 | 1746 |
2027 // Loop through the codecs list again to find the CN codec. | 1747 // Loop through the codecs list again to find the CN codec. |
2028 // TODO(solenberg): Break out into a separate function? | 1748 // TODO(solenberg): Break out into a separate function? |
2029 for (const AudioCodec& codec : codecs) { | 1749 for (const AudioCodec& codec : codecs) { |
2030 // Ignore codecs we don't know about. The negotiation step should prevent | |
2031 // this, but double-check to be sure. | |
2032 webrtc::CodecInst voe_codec = {0}; | |
2033 if (!WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) { | |
2034 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); | |
2035 continue; | |
2036 } | |
2037 | |
2038 if (IsCodec(codec, kCnCodecName)) { | 1750 if (IsCodec(codec, kCnCodecName)) { |
2039 // Turn voice activity detection/comfort noise on if supported. | 1751 // Turn voice activity detection/comfort noise on if supported. |
2040 // Set the wideband CN payload type appropriately. | 1752 // Set the wideband CN payload type appropriately. |
2041 // (narrowband always uses the static payload type 13). | 1753 // (narrowband always uses the static payload type 13). |
2042 int cng_plfreq = -1; | 1754 int cng_plfreq = -1; |
2043 switch (codec.clockrate) { | 1755 switch (codec.clockrate) { |
2044 case 8000: | 1756 case 8000: |
2045 case 16000: | 1757 case 16000: |
2046 case 32000: | 1758 case 32000: |
2047 cng_plfreq = codec.clockrate; | 1759 cng_plfreq = codec.clockrate; |
2048 break; | 1760 break; |
2049 default: | 1761 default: |
2050 LOG(LS_WARNING) << "CN frequency " << codec.clockrate | 1762 LOG(LS_WARNING) << "CN frequency " << codec.clockrate |
2051 << " not supported."; | 1763 << " not supported."; |
2052 continue; | 1764 continue; |
2053 } | 1765 } |
2054 send_codec_spec.cng_payload_type = codec.id; | 1766 send_codec_spec.cng_payload_type = codec.id; |
2055 send_codec_spec.cng_plfreq = cng_plfreq; | 1767 send_codec_spec.cng_plfreq = cng_plfreq; |
2056 break; | 1768 break; |
2057 } | 1769 } |
2058 } | 1770 } |
2059 | 1771 |
2060 // Find the telephone-event PT exactly matching the preferred send codec. | 1772 // Find the telephone-event PT exactly matching the preferred send codec. |
2061 for (const AudioCodec& dtmf_codec : dtmf_codecs) { | 1773 for (const AudioCodec& dtmf_codec : dtmf_codecs) { |
2062 if (dtmf_codec.clockrate == codec->clockrate) { | 1774 if (dtmf_codec.clockrate == chosen_codec->clockrate) { |
2063 dtmf_payload_type_ = rtc::Optional<int>(dtmf_codec.id); | 1775 dtmf_payload_type_ = rtc::Optional<int>(dtmf_codec.id); |
2064 dtmf_payload_freq_ = dtmf_codec.clockrate; | 1776 dtmf_payload_freq_ = dtmf_codec.clockrate; |
2065 break; | 1777 break; |
2066 } | 1778 } |
2067 } | 1779 } |
2068 } | 1780 } |
2069 | 1781 |
2070 if (send_codec_spec_ != send_codec_spec) { | 1782 if (send_codec_spec_ != send_codec_spec) { |
2071 send_codec_spec_ = std::move(send_codec_spec); | 1783 send_codec_spec_ = std::move(send_codec_spec); |
2072 // Apply new settings to all streams. | 1784 // Apply new settings to all streams. |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2202 // Save the channel to send_streams_, so that RemoveSendStream() can still | 1914 // Save the channel to send_streams_, so that RemoveSendStream() can still |
2203 // delete the channel in case failure happens below. | 1915 // delete the channel in case failure happens below. |
2204 webrtc::AudioTransport* audio_transport = | 1916 webrtc::AudioTransport* audio_transport = |
2205 engine()->voe()->base()->audio_transport(); | 1917 engine()->voe()->base()->audio_transport(); |
2206 | 1918 |
2207 rtc::Optional<std::string> audio_network_adaptor_config = | 1919 rtc::Optional<std::string> audio_network_adaptor_config = |
2208 GetAudioNetworkAdaptorConfig(options_); | 1920 GetAudioNetworkAdaptorConfig(options_); |
2209 WebRtcAudioSendStream* stream = new WebRtcAudioSendStream( | 1921 WebRtcAudioSendStream* stream = new WebRtcAudioSendStream( |
2210 channel, audio_transport, ssrc, sp.cname, send_codec_spec_, | 1922 channel, audio_transport, ssrc, sp.cname, send_codec_spec_, |
2211 send_rtp_extensions_, max_send_bitrate_bps_, audio_network_adaptor_config, | 1923 send_rtp_extensions_, max_send_bitrate_bps_, audio_network_adaptor_config, |
2212 call_, this); | 1924 call_, this, engine()->encoder_factory_); |
2213 send_streams_.insert(std::make_pair(ssrc, stream)); | 1925 send_streams_.insert(std::make_pair(ssrc, stream)); |
2214 | 1926 |
2215 // At this point the stream's local SSRC has been updated. If it is the first | 1927 // At this point the stream's local SSRC has been updated. If it is the first |
2216 // send stream, make sure that all the receive streams are updated with the | 1928 // send stream, make sure that all the receive streams are updated with the |
2217 // same SSRC in order to send receiver reports. | 1929 // same SSRC in order to send receiver reports. |
2218 if (send_streams_.size() == 1) { | 1930 if (send_streams_.size() == 1) { |
2219 receiver_reports_ssrc_ = ssrc; | 1931 receiver_reports_ssrc_ = ssrc; |
2220 for (const auto& kv : recv_streams_) { | 1932 for (const auto& kv : recv_streams_) { |
2221 // TODO(solenberg): Allow applications to set the RTCP SSRC of receive | 1933 // TODO(solenberg): Allow applications to set the RTCP SSRC of receive |
2222 // streams instead, so we can avoid recreating the streams here. | 1934 // streams instead, so we can avoid recreating the streams here. |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2698 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 2410 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
2699 const auto it = send_streams_.find(ssrc); | 2411 const auto it = send_streams_.find(ssrc); |
2700 if (it != send_streams_.end()) { | 2412 if (it != send_streams_.end()) { |
2701 return it->second->channel(); | 2413 return it->second->channel(); |
2702 } | 2414 } |
2703 return -1; | 2415 return -1; |
2704 } | 2416 } |
2705 } // namespace cricket | 2417 } // namespace cricket |
2706 | 2418 |
2707 #endif // HAVE_WEBRTC_VOICE | 2419 #endif // HAVE_WEBRTC_VOICE |
OLD | NEW |