OLD | NEW |
---|---|
1 /* | 1 /* |
2 * libjingle | 2 * libjingle |
3 * Copyright 2004 Google Inc. | 3 * Copyright 2004 Google Inc. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
140 // NOTE(ajm): Don't use hardcoded paths on platforms not explicitly specified | 140 // NOTE(ajm): Don't use hardcoded paths on platforms not explicitly specified |
141 // below. | 141 // below. |
142 #if defined(CHROMEOS) | 142 #if defined(CHROMEOS) |
143 static const char kAecDumpByAudioOptionFilename[] = "/tmp/audio.aecdump"; | 143 static const char kAecDumpByAudioOptionFilename[] = "/tmp/audio.aecdump"; |
144 #elif defined(ANDROID) | 144 #elif defined(ANDROID) |
145 static const char kAecDumpByAudioOptionFilename[] = "/sdcard/audio.aecdump"; | 145 static const char kAecDumpByAudioOptionFilename[] = "/sdcard/audio.aecdump"; |
146 #else | 146 #else |
147 static const char kAecDumpByAudioOptionFilename[] = "audio.aecdump"; | 147 static const char kAecDumpByAudioOptionFilename[] = "audio.aecdump"; |
148 #endif | 148 #endif |
149 | 149 |
150 namespace { | |
151 | |
152 bool ValidateStreamParams(const StreamParams& sp) { | |
153 if (sp.ssrcs.empty()) { | |
154 LOG(LS_ERROR) << "No SSRCs in stream parameters: " << sp.ToString(); | |
155 return false; | |
156 } | |
157 if (sp.ssrcs.size() > 1) { | |
158 LOG(LS_ERROR) << "Multiple SSRCs in stream parameters: " << sp.ToString(); | |
159 return false; | |
160 } | |
161 return true; | |
162 } | |
163 | |
150 // Dumps an AudioCodec in RFC 2327-ish format. | 164 // Dumps an AudioCodec in RFC 2327-ish format. |
151 static std::string ToString(const AudioCodec& codec) { | 165 std::string ToString(const AudioCodec& codec) { |
152 std::stringstream ss; | 166 std::stringstream ss; |
153 ss << codec.name << "/" << codec.clockrate << "/" << codec.channels | 167 ss << codec.name << "/" << codec.clockrate << "/" << codec.channels |
154 << " (" << codec.id << ")"; | 168 << " (" << codec.id << ")"; |
155 return ss.str(); | 169 return ss.str(); |
156 } | 170 } |
157 | 171 |
158 static std::string ToString(const webrtc::CodecInst& codec) { | 172 std::string ToString(const webrtc::CodecInst& codec) { |
159 std::stringstream ss; | 173 std::stringstream ss; |
160 ss << codec.plname << "/" << codec.plfreq << "/" << codec.channels | 174 ss << codec.plname << "/" << codec.plfreq << "/" << codec.channels |
161 << " (" << codec.pltype << ")"; | 175 << " (" << codec.pltype << ")"; |
162 return ss.str(); | 176 return ss.str(); |
163 } | 177 } |
164 | 178 |
165 static void LogMultiline(rtc::LoggingSeverity sev, char* text) { | 179 void LogMultiline(rtc::LoggingSeverity sev, char* text) { |
166 const char* delim = "\r\n"; | 180 const char* delim = "\r\n"; |
167 for (char* tok = strtok(text, delim); tok; tok = strtok(NULL, delim)) { | 181 for (char* tok = strtok(text, delim); tok; tok = strtok(NULL, delim)) { |
168 LOG_V(sev) << tok; | 182 LOG_V(sev) << tok; |
169 } | 183 } |
170 } | 184 } |
171 | 185 |
172 // Severity is an integer because it comes is assumed to be from command line. | 186 // Severity is an integer because it comes is assumed to be from command line. |
173 static int SeverityToFilter(int severity) { | 187 int SeverityToFilter(int severity) { |
174 int filter = webrtc::kTraceNone; | 188 int filter = webrtc::kTraceNone; |
175 switch (severity) { | 189 switch (severity) { |
176 case rtc::LS_VERBOSE: | 190 case rtc::LS_VERBOSE: |
177 filter |= webrtc::kTraceAll; | 191 filter |= webrtc::kTraceAll; |
178 FALLTHROUGH(); | 192 FALLTHROUGH(); |
179 case rtc::LS_INFO: | 193 case rtc::LS_INFO: |
180 filter |= (webrtc::kTraceStateInfo | webrtc::kTraceInfo); | 194 filter |= (webrtc::kTraceStateInfo | webrtc::kTraceInfo); |
181 FALLTHROUGH(); | 195 FALLTHROUGH(); |
182 case rtc::LS_WARNING: | 196 case rtc::LS_WARNING: |
183 filter |= (webrtc::kTraceTerseInfo | webrtc::kTraceWarning); | 197 filter |= (webrtc::kTraceTerseInfo | webrtc::kTraceWarning); |
184 FALLTHROUGH(); | 198 FALLTHROUGH(); |
185 case rtc::LS_ERROR: | 199 case rtc::LS_ERROR: |
186 filter |= (webrtc::kTraceError | webrtc::kTraceCritical); | 200 filter |= (webrtc::kTraceError | webrtc::kTraceCritical); |
187 } | 201 } |
188 return filter; | 202 return filter; |
189 } | 203 } |
190 | 204 |
191 static bool IsCodec(const AudioCodec& codec, const char* ref_name) { | 205 bool IsCodec(const AudioCodec& codec, const char* ref_name) { |
192 return (_stricmp(codec.name.c_str(), ref_name) == 0); | 206 return (_stricmp(codec.name.c_str(), ref_name) == 0); |
193 } | 207 } |
194 | 208 |
195 static bool IsCodec(const webrtc::CodecInst& codec, const char* ref_name) { | 209 bool IsCodec(const webrtc::CodecInst& codec, const char* ref_name) { |
196 return (_stricmp(codec.plname, ref_name) == 0); | 210 return (_stricmp(codec.plname, ref_name) == 0); |
197 } | 211 } |
198 | 212 |
199 static bool IsCodecMultiRate(const webrtc::CodecInst& codec) { | 213 bool IsCodecMultiRate(const webrtc::CodecInst& codec) { |
200 for (size_t i = 0; i < ARRAY_SIZE(kCodecPrefs); ++i) { | 214 for (size_t i = 0; i < ARRAY_SIZE(kCodecPrefs); ++i) { |
201 if (IsCodec(codec, kCodecPrefs[i].name) && | 215 if (IsCodec(codec, kCodecPrefs[i].name) && |
202 kCodecPrefs[i].clockrate == codec.plfreq) { | 216 kCodecPrefs[i].clockrate == codec.plfreq) { |
203 return kCodecPrefs[i].is_multi_rate; | 217 return kCodecPrefs[i].is_multi_rate; |
204 } | 218 } |
205 } | 219 } |
206 return false; | 220 return false; |
207 } | 221 } |
208 | 222 |
209 static bool FindCodec(const std::vector<AudioCodec>& codecs, | 223 bool FindCodec(const std::vector<AudioCodec>& codecs, |
210 const AudioCodec& codec, | 224 const AudioCodec& codec, |
211 AudioCodec* found_codec) { | 225 AudioCodec* found_codec) { |
212 for (const AudioCodec& c : codecs) { | 226 for (const AudioCodec& c : codecs) { |
213 if (c.Matches(codec)) { | 227 if (c.Matches(codec)) { |
214 if (found_codec != NULL) { | 228 if (found_codec != NULL) { |
215 *found_codec = c; | 229 *found_codec = c; |
216 } | 230 } |
217 return true; | 231 return true; |
218 } | 232 } |
219 } | 233 } |
220 return false; | 234 return false; |
221 } | 235 } |
222 | 236 |
223 static bool IsNackEnabled(const AudioCodec& codec) { | 237 bool IsNackEnabled(const AudioCodec& codec) { |
224 return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamNack, | 238 return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamNack, |
225 kParamValueEmpty)); | 239 kParamValueEmpty)); |
226 } | 240 } |
227 | 241 |
228 static int SelectPacketSize(const CodecPref& codec_pref, int ptime_ms) { | 242 int SelectPacketSize(const CodecPref& codec_pref, int ptime_ms) { |
229 int selected_packet_size_ms = codec_pref.packet_sizes_ms[0]; | 243 int selected_packet_size_ms = codec_pref.packet_sizes_ms[0]; |
230 for (int packet_size_ms : codec_pref.packet_sizes_ms) { | 244 for (int packet_size_ms : codec_pref.packet_sizes_ms) { |
231 if (packet_size_ms && packet_size_ms <= ptime_ms) { | 245 if (packet_size_ms && packet_size_ms <= ptime_ms) { |
232 selected_packet_size_ms = packet_size_ms; | 246 selected_packet_size_ms = packet_size_ms; |
233 } | 247 } |
234 } | 248 } |
235 return selected_packet_size_ms; | 249 return selected_packet_size_ms; |
236 } | 250 } |
237 | 251 |
238 // If the AudioCodec param kCodecParamPTime is set, then we will set it to codec | 252 // If the AudioCodec param kCodecParamPTime is set, then we will set it to codec |
239 // pacsize if it's valid, or we will pick the next smallest value we support. | 253 // pacsize if it's valid, or we will pick the next smallest value we support. |
240 // TODO(Brave): Query supported packet sizes from ACM when the API is ready. | 254 // TODO(Brave): Query supported packet sizes from ACM when the API is ready. |
241 static bool SetPTimeAsPacketSize(webrtc::CodecInst* codec, int ptime_ms) { | 255 bool SetPTimeAsPacketSize(webrtc::CodecInst* codec, int ptime_ms) { |
242 for (const CodecPref& codec_pref : kCodecPrefs) { | 256 for (const CodecPref& codec_pref : kCodecPrefs) { |
243 if ((IsCodec(*codec, codec_pref.name) && | 257 if ((IsCodec(*codec, codec_pref.name) && |
244 codec_pref.clockrate == codec->plfreq) || | 258 codec_pref.clockrate == codec->plfreq) || |
245 IsCodec(*codec, kG722CodecName)) { | 259 IsCodec(*codec, kG722CodecName)) { |
246 int packet_size_ms = SelectPacketSize(codec_pref, ptime_ms); | 260 int packet_size_ms = SelectPacketSize(codec_pref, ptime_ms); |
247 if (packet_size_ms) { | 261 if (packet_size_ms) { |
248 // Convert unit from milli-seconds to samples. | 262 // Convert unit from milli-seconds to samples. |
249 codec->pacsize = (codec->plfreq / 1000) * packet_size_ms; | 263 codec->pacsize = (codec->plfreq / 1000) * packet_size_ms; |
250 return true; | 264 return true; |
251 } | 265 } |
252 } | 266 } |
253 } | 267 } |
254 return false; | 268 return false; |
255 } | 269 } |
256 | 270 |
257 // Return true if codec.params[feature] == "1", false otherwise. | 271 // Return true if codec.params[feature] == "1", false otherwise. |
258 static bool IsCodecFeatureEnabled(const AudioCodec& codec, | 272 bool IsCodecFeatureEnabled(const AudioCodec& codec, |
259 const char* feature) { | 273 const char* feature) { |
260 int value; | 274 int value; |
261 return codec.GetParam(feature, &value) && value == 1; | 275 return codec.GetParam(feature, &value) && value == 1; |
262 } | 276 } |
263 | 277 |
264 // Use params[kCodecParamMaxAverageBitrate] if it is defined, use codec.bitrate | 278 // Use params[kCodecParamMaxAverageBitrate] if it is defined, use codec.bitrate |
265 // otherwise. If the value (either from params or codec.bitrate) <=0, use the | 279 // otherwise. If the value (either from params or codec.bitrate) <=0, use the |
266 // default configuration. If the value is beyond feasible bit rate of Opus, | 280 // default configuration. If the value is beyond feasible bit rate of Opus, |
267 // clamp it. Returns the Opus bit rate for operation. | 281 // clamp it. Returns the Opus bit rate for operation. |
268 static int GetOpusBitrate(const AudioCodec& codec, int max_playback_rate) { | 282 int GetOpusBitrate(const AudioCodec& codec, int max_playback_rate) { |
269 int bitrate = 0; | 283 int bitrate = 0; |
270 bool use_param = true; | 284 bool use_param = true; |
271 if (!codec.GetParam(kCodecParamMaxAverageBitrate, &bitrate)) { | 285 if (!codec.GetParam(kCodecParamMaxAverageBitrate, &bitrate)) { |
272 bitrate = codec.bitrate; | 286 bitrate = codec.bitrate; |
273 use_param = false; | 287 use_param = false; |
274 } | 288 } |
275 if (bitrate <= 0) { | 289 if (bitrate <= 0) { |
276 if (max_playback_rate <= 8000) { | 290 if (max_playback_rate <= 8000) { |
277 bitrate = kOpusBitrateNb; | 291 bitrate = kOpusBitrateNb; |
278 } else if (max_playback_rate <= 16000) { | 292 } else if (max_playback_rate <= 16000) { |
(...skipping 12 matching lines...) Expand all Loading... | |
291 "Supplied Opus bitrate"; | 305 "Supplied Opus bitrate"; |
292 LOG(LS_WARNING) << rate_source | 306 LOG(LS_WARNING) << rate_source |
293 << " is invalid and is replaced by: " | 307 << " is invalid and is replaced by: " |
294 << bitrate; | 308 << bitrate; |
295 } | 309 } |
296 return bitrate; | 310 return bitrate; |
297 } | 311 } |
298 | 312 |
299 // Returns kOpusDefaultPlaybackRate if params[kCodecParamMaxPlaybackRate] is not | 313 // Returns kOpusDefaultPlaybackRate if params[kCodecParamMaxPlaybackRate] is not |
300 // defined. Returns the value of params[kCodecParamMaxPlaybackRate] otherwise. | 314 // defined. Returns the value of params[kCodecParamMaxPlaybackRate] otherwise. |
301 static int GetOpusMaxPlaybackRate(const AudioCodec& codec) { | 315 int GetOpusMaxPlaybackRate(const AudioCodec& codec) { |
302 int value; | 316 int value; |
303 if (codec.GetParam(kCodecParamMaxPlaybackRate, &value)) { | 317 if (codec.GetParam(kCodecParamMaxPlaybackRate, &value)) { |
304 return value; | 318 return value; |
305 } | 319 } |
306 return kOpusDefaultMaxPlaybackRate; | 320 return kOpusDefaultMaxPlaybackRate; |
307 } | 321 } |
308 | 322 |
309 static void GetOpusConfig(const AudioCodec& codec, webrtc::CodecInst* voe_codec, | 323 void GetOpusConfig(const AudioCodec& codec, webrtc::CodecInst* voe_codec, |
310 bool* enable_codec_fec, int* max_playback_rate, | 324 bool* enable_codec_fec, int* max_playback_rate, |
311 bool* enable_codec_dtx) { | 325 bool* enable_codec_dtx) { |
312 *enable_codec_fec = IsCodecFeatureEnabled(codec, kCodecParamUseInbandFec); | 326 *enable_codec_fec = IsCodecFeatureEnabled(codec, kCodecParamUseInbandFec); |
313 *enable_codec_dtx = IsCodecFeatureEnabled(codec, kCodecParamUseDtx); | 327 *enable_codec_dtx = IsCodecFeatureEnabled(codec, kCodecParamUseDtx); |
314 *max_playback_rate = GetOpusMaxPlaybackRate(codec); | 328 *max_playback_rate = GetOpusMaxPlaybackRate(codec); |
315 | 329 |
316 // If OPUS, change what we send according to the "stereo" codec | 330 // If OPUS, change what we send according to the "stereo" codec |
317 // parameter, and not the "channels" parameter. We set | 331 // parameter, and not the "channels" parameter. We set |
318 // voe_codec.channels to 2 if "stereo=1" and 1 otherwise. If | 332 // voe_codec.channels to 2 if "stereo=1" and 1 otherwise. If |
319 // the bitrate is not specified, i.e. is <= zero, we set it to the | 333 // the bitrate is not specified, i.e. is <= zero, we set it to the |
320 // appropriate default value for mono or stereo Opus. | 334 // appropriate default value for mono or stereo Opus. |
321 | 335 |
322 voe_codec->channels = IsCodecFeatureEnabled(codec, kCodecParamStereo) ? 2 : 1; | 336 voe_codec->channels = IsCodecFeatureEnabled(codec, kCodecParamStereo) ? 2 : 1; |
323 voe_codec->rate = GetOpusBitrate(codec, *max_playback_rate); | 337 voe_codec->rate = GetOpusBitrate(codec, *max_playback_rate); |
324 } | 338 } |
325 | 339 |
326 // Changes RTP timestamp rate of G722. This is due to the "bug" in the RFC | 340 // Changes RTP timestamp rate of G722. This is due to the "bug" in the RFC |
327 // which says that G722 should be advertised as 8 kHz although it is a 16 kHz | 341 // which says that G722 should be advertised as 8 kHz although it is a 16 kHz |
328 // codec. | 342 // codec. |
329 static void MaybeFixupG722(webrtc::CodecInst* voe_codec, int new_plfreq) { | 343 void MaybeFixupG722(webrtc::CodecInst* voe_codec, int new_plfreq) { |
330 if (IsCodec(*voe_codec, kG722CodecName)) { | 344 if (IsCodec(*voe_codec, kG722CodecName)) { |
331 // If the ASSERT triggers, the codec definition in WebRTC VoiceEngine | 345 // If the ASSERT triggers, the codec definition in WebRTC VoiceEngine |
332 // has changed, and this special case is no longer needed. | 346 // has changed, and this special case is no longer needed. |
333 RTC_DCHECK(voe_codec->plfreq != new_plfreq); | 347 RTC_DCHECK(voe_codec->plfreq != new_plfreq); |
334 voe_codec->plfreq = new_plfreq; | 348 voe_codec->plfreq = new_plfreq; |
335 } | 349 } |
336 } | 350 } |
337 | 351 |
338 // Gets the default set of options applied to the engine. Historically, these | 352 // Gets the default set of options applied to the engine. Historically, these |
339 // were supplied as a combination of flags from the channel manager (ec, agc, | 353 // were supplied as a combination of flags from the channel manager (ec, agc, |
340 // ns, and highpass) and the rest hardcoded in InitInternal. | 354 // ns, and highpass) and the rest hardcoded in InitInternal. |
341 static AudioOptions GetDefaultEngineOptions() { | 355 AudioOptions GetDefaultEngineOptions() { |
342 AudioOptions options; | 356 AudioOptions options; |
343 options.echo_cancellation.Set(true); | 357 options.echo_cancellation.Set(true); |
344 options.auto_gain_control.Set(true); | 358 options.auto_gain_control.Set(true); |
345 options.noise_suppression.Set(true); | 359 options.noise_suppression.Set(true); |
346 options.highpass_filter.Set(true); | 360 options.highpass_filter.Set(true); |
347 options.stereo_swapping.Set(false); | 361 options.stereo_swapping.Set(false); |
348 options.audio_jitter_buffer_max_packets.Set(50); | 362 options.audio_jitter_buffer_max_packets.Set(50); |
349 options.audio_jitter_buffer_fast_accelerate.Set(false); | 363 options.audio_jitter_buffer_fast_accelerate.Set(false); |
350 options.typing_detection.Set(true); | 364 options.typing_detection.Set(true); |
351 options.conference_mode.Set(false); | |
352 options.adjust_agc_delta.Set(0); | 365 options.adjust_agc_delta.Set(0); |
353 options.experimental_agc.Set(false); | 366 options.experimental_agc.Set(false); |
354 options.extended_filter_aec.Set(false); | 367 options.extended_filter_aec.Set(false); |
355 options.delay_agnostic_aec.Set(false); | 368 options.delay_agnostic_aec.Set(false); |
356 options.experimental_ns.Set(false); | 369 options.experimental_ns.Set(false); |
357 options.aec_dump.Set(false); | 370 options.aec_dump.Set(false); |
358 return options; | 371 return options; |
359 } | 372 } |
360 | 373 |
361 static std::string GetEnableString(bool enable) { | 374 std::string GetEnableString(bool enable) { |
362 return enable ? "enable" : "disable"; | 375 return enable ? "enable" : "disable"; |
363 } | 376 } |
377 } // namespace { | |
364 | 378 |
365 WebRtcVoiceEngine::WebRtcVoiceEngine() | 379 WebRtcVoiceEngine::WebRtcVoiceEngine() |
366 : voe_wrapper_(new VoEWrapper()), | 380 : voe_wrapper_(new VoEWrapper()), |
367 tracing_(new VoETraceWrapper()), | 381 tracing_(new VoETraceWrapper()), |
368 adm_(NULL), | 382 adm_(NULL), |
369 log_filter_(SeverityToFilter(kDefaultLogSeverity)), | 383 log_filter_(SeverityToFilter(kDefaultLogSeverity)), |
370 is_dumping_aec_(false) { | 384 is_dumping_aec_(false) { |
371 Construct(); | 385 Construct(); |
372 } | 386 } |
373 | 387 |
(...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
855 if (options.playout_sample_rate.Get(&playout_sample_rate)) { | 869 if (options.playout_sample_rate.Get(&playout_sample_rate)) { |
856 LOG(LS_INFO) << "Playout sample rate is " << playout_sample_rate; | 870 LOG(LS_INFO) << "Playout sample rate is " << playout_sample_rate; |
857 if (voe_wrapper_->hw()->SetPlayoutSampleRate(playout_sample_rate)) { | 871 if (voe_wrapper_->hw()->SetPlayoutSampleRate(playout_sample_rate)) { |
858 LOG_RTCERR1(SetPlayoutSampleRate, playout_sample_rate); | 872 LOG_RTCERR1(SetPlayoutSampleRate, playout_sample_rate); |
859 } | 873 } |
860 } | 874 } |
861 | 875 |
862 return true; | 876 return true; |
863 } | 877 } |
864 | 878 |
865 struct ResumeEntry { | |
866 ResumeEntry(WebRtcVoiceMediaChannel *c, bool p, SendFlags s) | |
867 : channel(c), | |
868 playout(p), | |
869 send(s) { | |
870 } | |
871 | |
872 WebRtcVoiceMediaChannel *channel; | |
873 bool playout; | |
874 SendFlags send; | |
875 }; | |
876 | |
877 // TODO(juberti): Refactor this so that the core logic can be used to set the | 879 // TODO(juberti): Refactor this so that the core logic can be used to set the |
878 // soundclip device. At that time, reinstate the soundclip pause/resume code. | 880 // soundclip device. At that time, reinstate the soundclip pause/resume code. |
879 bool WebRtcVoiceEngine::SetDevices(const Device* in_device, | 881 bool WebRtcVoiceEngine::SetDevices(const Device* in_device, |
880 const Device* out_device) { | 882 const Device* out_device) { |
881 #if !defined(IOS) | 883 #if !defined(IOS) |
882 int in_id = in_device ? rtc::FromString<int>(in_device->id) : | 884 int in_id = in_device ? rtc::FromString<int>(in_device->id) : |
883 kDefaultAudioDeviceId; | 885 kDefaultAudioDeviceId; |
884 int out_id = out_device ? rtc::FromString<int>(out_device->id) : | 886 int out_id = out_device ? rtc::FromString<int>(out_device->id) : |
885 kDefaultAudioDeviceId; | 887 kDefaultAudioDeviceId; |
886 // The device manager uses -1 as the default device, which was the case for | 888 // The device manager uses -1 as the default device, which was the case for |
(...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1408 send_bitrate_bps_(0), | 1410 send_bitrate_bps_(0), |
1409 options_(), | 1411 options_(), |
1410 dtmf_allowed_(false), | 1412 dtmf_allowed_(false), |
1411 desired_playout_(false), | 1413 desired_playout_(false), |
1412 nack_enabled_(false), | 1414 nack_enabled_(false), |
1413 playout_(false), | 1415 playout_(false), |
1414 typing_noise_detected_(false), | 1416 typing_noise_detected_(false), |
1415 desired_send_(SEND_NOTHING), | 1417 desired_send_(SEND_NOTHING), |
1416 send_(SEND_NOTHING), | 1418 send_(SEND_NOTHING), |
1417 call_(call), | 1419 call_(call), |
1418 default_receive_ssrc_(0) { | 1420 default_recv_ssrc_(0), |
1421 default_recv_channel_id_(-1) { | |
1419 engine->RegisterChannel(this); | 1422 engine->RegisterChannel(this); |
1420 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel " | 1423 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel " |
1421 << voe_channel(); | 1424 << voe_channel(); |
1422 RTC_DCHECK(nullptr != call); | 1425 RTC_DCHECK(nullptr != call); |
1423 ConfigureSendChannel(voe_channel()); | 1426 ConfigureSendChannel(voe_channel()); |
1424 SetOptions(options); | 1427 SetOptions(options); |
1425 } | 1428 } |
1426 | 1429 |
1427 WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() { | 1430 WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() { |
1428 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel " | 1431 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel " |
1429 << voe_channel(); | 1432 << voe_channel(); |
1430 | 1433 |
1431 // Remove any remaining send streams, the default channel will be deleted | 1434 // Remove any remaining send streams, the default channel will be deleted |
1432 // later. | 1435 // later. |
1433 while (!send_channels_.empty()) | 1436 while (!send_channels_.empty()) { |
1434 RemoveSendStream(send_channels_.begin()->first); | 1437 RemoveSendStream(send_channels_.begin()->first); |
1438 } | |
1435 | 1439 |
1436 // Unregister ourselves from the engine. | 1440 // Unregister ourselves from the engine. |
1437 engine()->UnregisterChannel(this); | 1441 engine()->UnregisterChannel(this); |
1442 | |
1438 // Remove any remaining streams. | 1443 // Remove any remaining streams. |
1439 while (!receive_channels_.empty()) { | 1444 while (!receive_channels_.empty()) { |
1440 RemoveRecvStream(receive_channels_.begin()->first); | 1445 RemoveRecvStream(receive_channels_.begin()->first); |
1441 } | 1446 } |
1442 RTC_DCHECK(receive_streams_.empty()); | 1447 RTC_DCHECK(receive_streams_.empty()); |
1443 | 1448 |
1444 // Delete the default channel. | 1449 // Delete the default channel. |
1445 DeleteChannel(voe_channel()); | 1450 DeleteChannel(voe_channel()); |
1446 } | 1451 } |
1447 | 1452 |
1448 bool WebRtcVoiceMediaChannel::SetSendParameters( | 1453 bool WebRtcVoiceMediaChannel::SetSendParameters( |
1449 const AudioSendParameters& params) { | 1454 const AudioSendParameters& params) { |
1450 // TODO(pthatcher): Refactor this to be more clean now that we have | 1455 // TODO(pthatcher): Refactor this to be more clean now that we have |
1451 // all the information at once. | 1456 // all the information at once. |
1452 return (SetSendCodecs(params.codecs) && | 1457 return (SetSendCodecs(params.codecs) && |
1453 SetSendRtpHeaderExtensions(params.extensions) && | 1458 SetSendRtpHeaderExtensions(params.extensions) && |
1454 SetMaxSendBandwidth(params.max_bandwidth_bps) && | 1459 SetMaxSendBandwidth(params.max_bandwidth_bps) && |
1455 SetOptions(params.options)); | 1460 SetOptions(params.options)); |
1456 } | 1461 } |
1457 | 1462 |
1458 bool WebRtcVoiceMediaChannel::SetRecvParameters( | 1463 bool WebRtcVoiceMediaChannel::SetRecvParameters( |
1459 const AudioRecvParameters& params) { | 1464 const AudioRecvParameters& params) { |
1460 // TODO(pthatcher): Refactor this to be more clean now that we have | 1465 // TODO(pthatcher): Refactor this to be more clean now that we have |
1461 // all the information at once. | 1466 // all the information at once. |
1462 return (SetRecvCodecs(params.codecs) && | 1467 return (SetRecvCodecs(params.codecs) && |
1463 SetRecvRtpHeaderExtensions(params.extensions)); | 1468 SetRecvRtpHeaderExtensions(params.extensions)); |
1464 } | 1469 } |
1465 | 1470 |
1466 bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) { | 1471 bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) { |
1472 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | |
pthatcher1
2015/10/02 02:33:31
This is called in the following methods:
WebRtcVo
the sun
2015/10/02 11:34:19
Done.
| |
1467 LOG(LS_INFO) << "Setting voice channel options: " | 1473 LOG(LS_INFO) << "Setting voice channel options: " |
1468 << options.ToString(); | 1474 << options.ToString(); |
1469 | 1475 |
1470 // Check if DSCP value is changed from previous. | 1476 // Check if DSCP value is changed from previous. |
1471 bool dscp_option_changed = (options_.dscp != options.dscp); | 1477 bool dscp_option_changed = (options_.dscp != options.dscp); |
1472 | 1478 |
1473 // TODO(xians): Add support to set different options for different send | 1479 // TODO(xians): Add support to set different options for different send |
1474 // streams after we support multiple APMs. | 1480 // streams after we support multiple APMs. |
1475 | 1481 |
1476 // We retain all of the existing options, and apply the given ones | 1482 // We retain all of the existing options, and apply the given ones |
1477 // on top. This means there is no way to "clear" options such that | 1483 // on top. This means there is no way to "clear" options such that |
1478 // they go back to the engine default. | 1484 // they go back to the engine default. |
1479 options_.SetAll(options); | 1485 options_.SetAll(options); |
1480 | 1486 |
1481 if (send_ != SEND_NOTHING) { | 1487 if (send_ != SEND_NOTHING) { |
1482 if (!engine()->ApplyOptions(options_)) { | 1488 if (!engine()->ApplyOptions(options_)) { |
1483 LOG(LS_WARNING) << | 1489 LOG(LS_WARNING) << |
1484 "Failed to apply engine options during channel SetOptions."; | 1490 "Failed to apply engine options during channel SetOptions."; |
1485 return false; | 1491 return false; |
1486 } | 1492 } |
1487 } | 1493 } |
1488 | 1494 |
1495 // TODO(solenberg): !!!!!! | |
1496 SetRecvOptions(voe_channel()); | |
pthatcher1
2015/10/02 02:33:31
Why do we have to call SetRecvOptions with the def
the sun
2015/10/02 11:34:20
Sorry; debugging left overs.
| |
1497 for (const auto& ch : receive_channels_) { | |
1498 if (!SetRecvOptions(ch.second->channel())) { | |
1499 return false; | |
1500 } | |
1501 } | |
1502 if (dscp_option_changed) { | |
1503 rtc::DiffServCodePoint dscp = rtc::DSCP_DEFAULT; | |
1504 if (options_.dscp.GetWithDefaultIfUnset(false)) | |
1505 dscp = kAudioDscpValue; | |
1506 if (MediaChannel::SetDscp(dscp) != 0) { | |
1507 LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel"; | |
1508 } | |
1509 } | |
1510 | |
1511 RecreateAudioReceiveStreams(); | |
1512 | |
1513 LOG(LS_INFO) << "Set voice channel options. Current options: " | |
1514 << options_.ToString(); | |
1515 return true; | |
1516 } | |
1517 | |
1518 bool WebRtcVoiceMediaChannel::SetRecvOptions(int channel_id) { | |
pthatcher1
2015/10/02 02:33:31
Can you please pass option into here as well?
the sun
2015/10/02 11:34:20
Done.
| |
1519 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | |
1520 | |
1489 // Receiver-side auto gain control happens per channel, so set it here from | 1521 // Receiver-side auto gain control happens per channel, so set it here from |
1490 // options. Note that, like conference mode, setting it on the engine won't | 1522 // options. Note that voice channels don't inherit options from the media |
1491 // have the desired effect, since voice channels don't inherit options from | 1523 // engine when those options are applied per-channel. |
1492 // the media engine when those options are applied per-channel. | |
1493 bool rx_auto_gain_control; | 1524 bool rx_auto_gain_control; |
1494 if (options.rx_auto_gain_control.Get(&rx_auto_gain_control)) { | 1525 if (options_.rx_auto_gain_control.Get(&rx_auto_gain_control)) { |
1495 if (engine()->voe()->processing()->SetRxAgcStatus( | 1526 if (engine()->voe()->processing()->SetRxAgcStatus( |
1496 voe_channel(), rx_auto_gain_control, | 1527 channel_id, rx_auto_gain_control, |
1497 webrtc::kAgcFixedDigital) == -1) { | 1528 webrtc::kAgcFixedDigital) == -1) { |
1498 LOG_RTCERR1(SetRxAgcStatus, rx_auto_gain_control); | 1529 LOG_RTCERR1(SetRxAgcStatus, rx_auto_gain_control); |
1499 return false; | 1530 return false; |
1500 } else { | 1531 } else { |
1501 LOG(LS_VERBOSE) << "Rx auto gain set to " << rx_auto_gain_control | 1532 LOG(LS_VERBOSE) << "Rx auto gain set to " << rx_auto_gain_control |
1502 << " with mode " << webrtc::kAgcFixedDigital; | 1533 << " with mode " << webrtc::kAgcFixedDigital; |
1503 } | 1534 } |
1504 } | 1535 } |
1505 if (options.rx_agc_target_dbov.IsSet() || | 1536 if (options_.rx_agc_target_dbov.IsSet() || |
1506 options.rx_agc_digital_compression_gain.IsSet() || | 1537 options_.rx_agc_digital_compression_gain.IsSet() || |
1507 options.rx_agc_limiter.IsSet()) { | 1538 options_.rx_agc_limiter.IsSet()) { |
1508 webrtc::AgcConfig config; | 1539 webrtc::AgcConfig config; |
1509 // If only some of the options are being overridden, get the current | 1540 // If only some of the options are being overridden, get the current |
1510 // settings for the channel and bail if they aren't available. | 1541 // settings for the channel and bail if they aren't available. |
1511 if (!options.rx_agc_target_dbov.IsSet() || | 1542 if (!options_.rx_agc_target_dbov.IsSet() || |
1512 !options.rx_agc_digital_compression_gain.IsSet() || | 1543 !options_.rx_agc_digital_compression_gain.IsSet() || |
1513 !options.rx_agc_limiter.IsSet()) { | 1544 !options_.rx_agc_limiter.IsSet()) { |
1514 if (engine()->voe()->processing()->GetRxAgcConfig( | 1545 if (engine()->voe()->processing()->GetRxAgcConfig( |
1515 voe_channel(), config) != 0) { | 1546 channel_id, config) != 0) { |
1516 LOG(LS_ERROR) << "Failed to get default rx agc configuration for " | 1547 LOG(LS_ERROR) << "Failed to get default rx agc configuration for " |
1517 << "channel " << voe_channel() << ". Since not all rx " | 1548 << "channel " << channel_id << ". Since not all rx " |
1518 << "agc options are specified, unable to safely set rx " | 1549 << "agc options are specified, unable to safely set rx " |
1519 << "agc options."; | 1550 << "agc options."; |
1520 return false; | 1551 return false; |
1521 } | 1552 } |
1522 } | 1553 } |
1523 config.targetLeveldBOv = | 1554 config.targetLeveldBOv = |
1524 options.rx_agc_target_dbov.GetWithDefaultIfUnset( | 1555 options_.rx_agc_target_dbov.GetWithDefaultIfUnset( |
1525 config.targetLeveldBOv); | 1556 config.targetLeveldBOv); |
1526 config.digitalCompressionGaindB = | 1557 config.digitalCompressionGaindB = |
1527 options.rx_agc_digital_compression_gain.GetWithDefaultIfUnset( | 1558 options_.rx_agc_digital_compression_gain.GetWithDefaultIfUnset( |
1528 config.digitalCompressionGaindB); | 1559 config.digitalCompressionGaindB); |
1529 config.limiterEnable = options.rx_agc_limiter.GetWithDefaultIfUnset( | 1560 config.limiterEnable = options_.rx_agc_limiter.GetWithDefaultIfUnset( |
1530 config.limiterEnable); | 1561 config.limiterEnable); |
1531 if (engine()->voe()->processing()->SetRxAgcConfig( | 1562 if (engine()->voe()->processing()->SetRxAgcConfig( |
1532 voe_channel(), config) == -1) { | 1563 channel_id, config) == -1) { |
1533 LOG_RTCERR4(SetRxAgcConfig, voe_channel(), config.targetLeveldBOv, | 1564 LOG_RTCERR4(SetRxAgcConfig, channel_id, config.targetLeveldBOv, |
1534 config.digitalCompressionGaindB, config.limiterEnable); | 1565 config.digitalCompressionGaindB, config.limiterEnable); |
1535 return false; | 1566 return false; |
1536 } | 1567 } |
1537 } | 1568 } |
1538 if (dscp_option_changed) { | |
1539 rtc::DiffServCodePoint dscp = rtc::DSCP_DEFAULT; | |
1540 if (options_.dscp.GetWithDefaultIfUnset(false)) | |
1541 dscp = kAudioDscpValue; | |
1542 if (MediaChannel::SetDscp(dscp) != 0) { | |
1543 LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel"; | |
1544 } | |
1545 } | |
1546 | |
1547 RecreateAudioReceiveStreams(); | |
1548 | |
1549 LOG(LS_INFO) << "Set voice channel options. Current options: " | |
1550 << options_.ToString(); | |
1551 return true; | 1569 return true; |
1552 } | 1570 } |
1553 | 1571 |
1554 bool WebRtcVoiceMediaChannel::SetRecvCodecs( | 1572 bool WebRtcVoiceMediaChannel::SetRecvCodecs( |
1555 const std::vector<AudioCodec>& codecs) { | 1573 const std::vector<AudioCodec>& codecs) { |
1556 // Set the payload types to be used for incoming media. | 1574 // Set the payload types to be used for incoming media. |
1557 LOG(LS_INFO) << "Setting receive voice codecs:"; | 1575 LOG(LS_INFO) << "Setting receive voice codecs:"; |
1558 | 1576 |
1577 std::vector<int> payload_types; | |
1559 std::vector<AudioCodec> new_codecs; | 1578 std::vector<AudioCodec> new_codecs; |
1560 // Find all new codecs. We allow adding new codecs but don't allow changing | 1579 // Find all new codecs. We allow adding new codecs but don't allow changing |
1561 // the payload type of codecs that is already configured since we might | 1580 // the payload type of codecs that is already configured since we might |
1562 // already be receiving packets with that payload type. | 1581 // already be receiving packets with that payload type. |
1563 for (const AudioCodec& codec : codecs) { | 1582 for (const auto& codec : codecs) { |
1564 AudioCodec old_codec; | 1583 AudioCodec old_codec; |
1565 if (FindCodec(recv_codecs_, codec, &old_codec)) { | 1584 if (FindCodec(recv_codecs_, codec, &old_codec)) { |
1566 if (old_codec.id != codec.id) { | 1585 if (old_codec.id != codec.id) { |
1567 LOG(LS_ERROR) << codec.name << " payload type changed."; | 1586 LOG(LS_ERROR) << codec.name << " payload type changed."; |
1568 return false; | 1587 return false; |
1569 } | 1588 } |
1570 } else { | 1589 } else { |
1590 payload_types.push_back(codec.id); | |
1571 new_codecs.push_back(codec); | 1591 new_codecs.push_back(codec); |
1572 } | 1592 } |
1573 } | 1593 } |
1574 if (new_codecs.empty()) { | 1594 if (new_codecs.empty()) { |
1575 // There are no new codecs to configure. Already configured codecs are | 1595 // There are no new codecs to configure. Already configured codecs are |
1576 // never removed. | 1596 // never removed. |
1577 return true; | 1597 return true; |
1578 } | 1598 } |
1579 | 1599 |
1600 // Verify no codecs have the same payload type. | |
pthatcher1
2015/10/02 02:33:31
Can you put this in its own helper function?
the sun
2015/10/02 11:34:20
Done.
| |
1601 std::sort(payload_types.begin(), payload_types.end()); | |
1602 auto it = std::unique(payload_types.begin(), payload_types.end()); | |
1603 if (payload_types.end() != it) { | |
1604 return false; | |
1605 } | |
1606 | |
1580 if (playout_) { | 1607 if (playout_) { |
1581 // Receive codecs can not be changed while playing. So we temporarily | 1608 // Receive codecs can not be changed while playing. So we temporarily |
1582 // pause playout. | 1609 // pause playout. |
1583 PausePlayout(); | 1610 PausePlayout(); |
1584 } | 1611 } |
1585 | 1612 |
1586 bool result = SetRecvCodecsInternal(new_codecs); | 1613 bool result = SetRecvCodecsInternal(new_codecs); |
1587 if (result) { | 1614 if (result) { |
1588 recv_codecs_ = codecs; | 1615 recv_codecs_ = codecs; |
1589 } | 1616 } |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1797 return false; | 1824 return false; |
1798 } | 1825 } |
1799 } | 1826 } |
1800 } | 1827 } |
1801 } | 1828 } |
1802 return true; | 1829 return true; |
1803 } | 1830 } |
1804 | 1831 |
1805 bool WebRtcVoiceMediaChannel::SetSendCodecs( | 1832 bool WebRtcVoiceMediaChannel::SetSendCodecs( |
1806 const std::vector<AudioCodec>& codecs) { | 1833 const std::vector<AudioCodec>& codecs) { |
1834 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | |
pthatcher1
2015/10/02 02:33:31
This is called by
WebRtcVoiceMediaChannel::SetSe
the sun
2015/10/02 11:34:20
Done.
| |
1807 dtmf_allowed_ = false; | 1835 dtmf_allowed_ = false; |
1808 for (const AudioCodec& codec : codecs) { | 1836 for (const AudioCodec& codec : codecs) { |
1809 // Find the DTMF telephone event "codec". | 1837 // Find the DTMF telephone event "codec". |
1810 if (IsCodec(codec, kDtmfCodecName)) { | 1838 if (IsCodec(codec, kDtmfCodecName)) { |
1811 dtmf_allowed_ = true; | 1839 dtmf_allowed_ = true; |
1812 } | 1840 } |
1813 } | 1841 } |
1814 | 1842 |
1815 // Cache the codecs in order to configure the channel created later. | 1843 // Cache the codecs in order to configure the channel created later. |
1816 send_codecs_ = codecs; | 1844 send_codecs_ = codecs; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1868 | 1896 |
1869 if (engine()->voe()->codec()->SetSendCodec(channel, send_codec) == -1) { | 1897 if (engine()->voe()->codec()->SetSendCodec(channel, send_codec) == -1) { |
1870 LOG_RTCERR2(SetSendCodec, channel, ToString(send_codec)); | 1898 LOG_RTCERR2(SetSendCodec, channel, ToString(send_codec)); |
1871 return false; | 1899 return false; |
1872 } | 1900 } |
1873 return true; | 1901 return true; |
1874 } | 1902 } |
1875 | 1903 |
1876 bool WebRtcVoiceMediaChannel::SetRecvRtpHeaderExtensions( | 1904 bool WebRtcVoiceMediaChannel::SetRecvRtpHeaderExtensions( |
1877 const std::vector<RtpHeaderExtension>& extensions) { | 1905 const std::vector<RtpHeaderExtension>& extensions) { |
1906 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | |
pthatcher1
2015/10/02 02:33:31
This is called by WebRtcVoiceMediaChannel::SetRecv
the sun
2015/10/02 11:34:19
Done.
| |
1878 if (receive_extensions_ == extensions) { | 1907 if (receive_extensions_ == extensions) { |
1879 return true; | 1908 return true; |
1880 } | 1909 } |
1881 | 1910 |
1882 // The default channel may or may not be in |receive_channels_|. Set the rtp | |
1883 // header extensions for default channel regardless. | |
1884 if (!SetChannelRecvRtpHeaderExtensions(voe_channel(), extensions)) { | |
1885 return false; | |
1886 } | |
1887 | |
1888 // Loop through all receive channels and enable/disable the extensions. | |
1889 for (const auto& ch : receive_channels_) { | 1911 for (const auto& ch : receive_channels_) { |
1890 if (!SetChannelRecvRtpHeaderExtensions(ch.second->channel(), extensions)) { | 1912 if (!SetChannelRecvRtpHeaderExtensions(ch.second->channel(), extensions)) { |
1891 return false; | 1913 return false; |
1892 } | 1914 } |
1893 } | 1915 } |
1894 | 1916 |
1895 receive_extensions_ = extensions; | 1917 receive_extensions_ = extensions; |
1896 | 1918 |
1897 // Recreate AudioReceiveStream:s. | 1919 // Recreate AudioReceiveStream:s. |
1898 { | 1920 { |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1993 | 2015 |
1994 bool WebRtcVoiceMediaChannel::PausePlayout() { | 2016 bool WebRtcVoiceMediaChannel::PausePlayout() { |
1995 return ChangePlayout(false); | 2017 return ChangePlayout(false); |
1996 } | 2018 } |
1997 | 2019 |
1998 bool WebRtcVoiceMediaChannel::ResumePlayout() { | 2020 bool WebRtcVoiceMediaChannel::ResumePlayout() { |
1999 return ChangePlayout(desired_playout_); | 2021 return ChangePlayout(desired_playout_); |
2000 } | 2022 } |
2001 | 2023 |
2002 bool WebRtcVoiceMediaChannel::ChangePlayout(bool playout) { | 2024 bool WebRtcVoiceMediaChannel::ChangePlayout(bool playout) { |
2025 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | |
2003 if (playout_ == playout) { | 2026 if (playout_ == playout) { |
2004 return true; | 2027 return true; |
2005 } | 2028 } |
2006 | 2029 |
2007 // Change the playout of all channels to the new state. | 2030 // Change the playout of all channels to the new state. |
2008 bool result = true; | 2031 bool result = true; |
2009 if (receive_channels_.empty()) { | |
2010 // Only toggle the default channel if we don't have any other channels. | |
2011 result = SetPlayout(voe_channel(), playout); | |
2012 } | |
2013 for (const auto& ch : receive_channels_) { | 2032 for (const auto& ch : receive_channels_) { |
2014 if (!SetPlayout(ch.second->channel(), playout)) { | 2033 if (!SetPlayout(ch.second->channel(), playout)) { |
2015 LOG(LS_ERROR) << "SetPlayout " << playout << " on channel " | 2034 LOG(LS_ERROR) << "SetPlayout " << playout << " on channel " |
2016 << ch.second->channel() << " failed"; | 2035 << ch.second->channel() << " failed"; |
2017 result = false; | 2036 result = false; |
2018 break; | 2037 break; |
2019 } | 2038 } |
2020 } | 2039 } |
2021 | 2040 |
2022 if (result) { | 2041 if (result) { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2105 // TODO(ronghuawu): Change this method to return bool. | 2124 // TODO(ronghuawu): Change this method to return bool. |
2106 void WebRtcVoiceMediaChannel::ConfigureSendChannel(int channel) { | 2125 void WebRtcVoiceMediaChannel::ConfigureSendChannel(int channel) { |
2107 if (engine()->voe()->network()->RegisterExternalTransport( | 2126 if (engine()->voe()->network()->RegisterExternalTransport( |
2108 channel, *this) == -1) { | 2127 channel, *this) == -1) { |
2109 LOG_RTCERR2(RegisterExternalTransport, channel, this); | 2128 LOG_RTCERR2(RegisterExternalTransport, channel, this); |
2110 } | 2129 } |
2111 | 2130 |
2112 // Enable RTCP (for quality stats and feedback messages) | 2131 // Enable RTCP (for quality stats and feedback messages) |
2113 EnableRtcp(channel); | 2132 EnableRtcp(channel); |
2114 | 2133 |
2115 // Reset all recv codecs; they will be enabled via SetRecvCodecs. | |
2116 ResetRecvCodecs(channel); | |
2117 | |
2118 // Set RTP header extension for the new channel. | 2134 // Set RTP header extension for the new channel. |
2119 SetChannelSendRtpHeaderExtensions(channel, send_extensions_); | 2135 SetChannelSendRtpHeaderExtensions(channel, send_extensions_); |
2120 } | 2136 } |
2121 | 2137 |
2122 bool WebRtcVoiceMediaChannel::DeleteChannel(int channel) { | 2138 bool WebRtcVoiceMediaChannel::DeleteChannel(int channel) { |
2123 if (engine()->voe()->network()->DeRegisterExternalTransport(channel) == -1) { | 2139 if (engine()->voe()->network()->DeRegisterExternalTransport(channel) == -1) { |
2124 LOG_RTCERR1(DeRegisterExternalTransport, channel); | 2140 LOG_RTCERR1(DeRegisterExternalTransport, channel); |
2125 } | 2141 } |
2126 | 2142 |
2127 if (engine()->voe()->base()->DeleteChannel(channel) == -1) { | 2143 if (engine()->voe()->base()->DeleteChannel(channel) == -1) { |
2128 LOG_RTCERR1(DeleteChannel, channel); | 2144 LOG_RTCERR1(DeleteChannel, channel); |
2129 return false; | 2145 return false; |
2130 } | 2146 } |
2131 | 2147 |
2132 return true; | 2148 return true; |
2133 } | 2149 } |
2134 | 2150 |
2135 bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) { | 2151 bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) { |
2152 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | |
2136 // If the default channel is already used for sending create a new channel | 2153 // If the default channel is already used for sending create a new channel |
2137 // otherwise use the default channel for sending. | 2154 // otherwise use the default channel for sending. |
2138 int channel = GetSendChannelNum(sp.first_ssrc()); | 2155 int channel = GetSendChannelNum(sp.first_ssrc()); |
2139 if (channel != -1) { | 2156 if (channel != -1) { |
2140 LOG(LS_ERROR) << "Stream already exists with ssrc " << sp.first_ssrc(); | 2157 LOG(LS_ERROR) << "Stream already exists with ssrc " << sp.first_ssrc(); |
2141 return false; | 2158 return false; |
2142 } | 2159 } |
2143 | 2160 |
2144 bool default_channel_is_available = true; | 2161 bool default_channel_is_available = true; |
2145 for (const auto& ch : send_channels_) { | 2162 for (const auto& ch : send_channels_) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2177 LOG_RTCERR2(SetSendSSRC, channel, sp.first_ssrc()); | 2194 LOG_RTCERR2(SetSendSSRC, channel, sp.first_ssrc()); |
2178 return false; | 2195 return false; |
2179 } | 2196 } |
2180 | 2197 |
2181 // At this point the channel's local SSRC has been updated. If the channel is | 2198 // At this point the channel's local SSRC has been updated. If the channel is |
2182 // the default channel make sure that all the receive channels are updated as | 2199 // the default channel make sure that all the receive channels are updated as |
2183 // well. Receive channels have to have the same SSRC as the default channel in | 2200 // well. Receive channels have to have the same SSRC as the default channel in |
2184 // order to send receiver reports with this SSRC. | 2201 // order to send receiver reports with this SSRC. |
2185 if (IsDefaultChannel(channel)) { | 2202 if (IsDefaultChannel(channel)) { |
2186 for (const auto& ch : receive_channels_) { | 2203 for (const auto& ch : receive_channels_) { |
2187 // Only update the SSRC for non-default channels. | 2204 if (engine()->voe()->rtp()->SetLocalSSRC(ch.second->channel(), |
2188 if (!IsDefaultChannel(ch.second->channel())) { | 2205 sp.first_ssrc()) != 0) { |
2189 if (engine()->voe()->rtp()->SetLocalSSRC(ch.second->channel(), | 2206 LOG_RTCERR2(SetLocalSSRC, ch.second->channel(), sp.first_ssrc()); |
2190 sp.first_ssrc()) != 0) { | 2207 return false; |
2191 LOG_RTCERR2(SetLocalSSRC, ch.second->channel(), sp.first_ssrc()); | |
2192 return false; | |
2193 } | |
2194 } | 2208 } |
2195 } | 2209 } |
2196 } | 2210 } |
2197 | 2211 |
2198 if (engine()->voe()->rtp()->SetRTCP_CNAME(channel, sp.cname.c_str()) == -1) { | 2212 if (engine()->voe()->rtp()->SetRTCP_CNAME(channel, sp.cname.c_str()) == -1) { |
2199 LOG_RTCERR2(SetRTCP_CNAME, channel, sp.cname); | 2213 LOG_RTCERR2(SetRTCP_CNAME, channel, sp.cname); |
2200 return false; | 2214 return false; |
2201 } | 2215 } |
2202 | 2216 |
2203 // Set the current codecs to be used for the new channel. | 2217 // Set the current codecs to be used for the new channel. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2236 } | 2250 } |
2237 | 2251 |
2238 if (send_channels_.empty()) | 2252 if (send_channels_.empty()) |
2239 ChangeSend(SEND_NOTHING); | 2253 ChangeSend(SEND_NOTHING); |
2240 | 2254 |
2241 return true; | 2255 return true; |
2242 } | 2256 } |
2243 | 2257 |
2244 bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) { | 2258 bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) { |
2245 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 2259 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
2246 rtc::CritScope lock(&receive_channels_cs_); | 2260 LOG(LS_INFO) << "AddRecvStream: " << sp.ToString(); |
2247 | 2261 |
2248 if (!VERIFY(sp.ssrcs.size() == 1)) | 2262 if (!ValidateStreamParams(sp)) { |
2249 return false; | 2263 return false; |
2264 } | |
2265 | |
2250 uint32 ssrc = sp.first_ssrc(); | 2266 uint32 ssrc = sp.first_ssrc(); |
2267 if (ssrc == 0) { | |
2268 LOG(LS_WARNING) << "AddRecvStream with ssrc==0 is not supported."; | |
2269 return false; | |
2270 } | |
2251 | 2271 |
2252 if (ssrc == 0) { | 2272 // Remove the default receive stream if one had been created with this ssrc; |
2253 LOG(LS_WARNING) << "AddRecvStream with 0 ssrc is not supported."; | 2273 // we'll recreate it then. |
2254 return false; | 2274 if (-1 != default_recv_channel_id_ && ssrc == default_recv_ssrc_) { |
2275 RemoveRecvStream(ssrc); | |
pthatcher1
2015/10/02 02:33:30
Why remove it and re-add it? Why not just keep us
the sun
2015/10/02 11:34:19
Because we need to recreate the AudioReceiveStream
| |
2255 } | 2276 } |
2256 | 2277 |
2257 if (receive_channels_.find(ssrc) != receive_channels_.end()) { | 2278 if (receive_channels_.find(ssrc) != receive_channels_.end()) { |
2258 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc; | 2279 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc; |
2259 return false; | 2280 return false; |
2260 } | 2281 } |
2261 | |
2262 RTC_DCHECK(receive_stream_params_.find(ssrc) == receive_stream_params_.end()); | 2282 RTC_DCHECK(receive_stream_params_.find(ssrc) == receive_stream_params_.end()); |
2263 | 2283 |
2264 // Reuse default channel for recv stream in non-conference mode call | |
2265 // when the default channel is not being used. | |
2266 webrtc::AudioTransport* audio_transport = | |
2267 engine()->voe()->base()->audio_transport(); | |
2268 if (!InConferenceMode() && default_receive_ssrc_ == 0) { | |
2269 LOG(LS_INFO) << "Recv stream " << ssrc << " reuse default channel"; | |
2270 default_receive_ssrc_ = ssrc; | |
2271 WebRtcVoiceChannelRenderer* channel_renderer = | |
2272 new WebRtcVoiceChannelRenderer(voe_channel(), audio_transport); | |
2273 receive_channels_.insert(std::make_pair(ssrc, channel_renderer)); | |
2274 receive_stream_params_[ssrc] = sp; | |
2275 AddAudioReceiveStream(ssrc); | |
2276 return SetPlayout(voe_channel(), playout_); | |
2277 } | |
2278 | |
2279 // Create a new channel for receiving audio data. | 2284 // Create a new channel for receiving audio data. |
2280 int channel = engine()->CreateMediaVoiceChannel(); | 2285 int channel = engine()->CreateMediaVoiceChannel(); |
2281 if (channel == -1) { | 2286 if (channel == -1) { |
2282 LOG_RTCERR0(CreateChannel); | 2287 LOG_RTCERR0(CreateChannel); |
2283 return false; | 2288 return false; |
2284 } | 2289 } |
2285 | |
2286 if (!ConfigureRecvChannel(channel)) { | 2290 if (!ConfigureRecvChannel(channel)) { |
2287 DeleteChannel(channel); | 2291 DeleteChannel(channel); |
2288 return false; | 2292 return false; |
2289 } | 2293 } |
2290 | 2294 |
2295 webrtc::AudioTransport* audio_transport = | |
2296 engine()->voe()->base()->audio_transport(); | |
2291 WebRtcVoiceChannelRenderer* channel_renderer = | 2297 WebRtcVoiceChannelRenderer* channel_renderer = |
2292 new WebRtcVoiceChannelRenderer(channel, audio_transport); | 2298 new WebRtcVoiceChannelRenderer(channel, audio_transport); |
2293 receive_channels_.insert(std::make_pair(ssrc, channel_renderer)); | 2299 receive_channels_.insert(std::make_pair(ssrc, channel_renderer)); |
2294 receive_stream_params_[ssrc] = sp; | 2300 receive_stream_params_[ssrc] = sp; |
2295 AddAudioReceiveStream(ssrc); | 2301 AddAudioReceiveStream(ssrc); |
2296 | 2302 |
2297 LOG(LS_INFO) << "New audio stream " << ssrc | 2303 LOG(LS_INFO) << "New audio stream " << ssrc |
2298 << " registered to VoiceEngine channel #" | 2304 << " registered to VoiceEngine channel #" |
2299 << channel << "."; | 2305 << channel << "."; |
2300 return true; | 2306 return true; |
2301 } | 2307 } |
2302 | 2308 |
2303 bool WebRtcVoiceMediaChannel::ConfigureRecvChannel(int channel) { | 2309 bool WebRtcVoiceMediaChannel::ConfigureRecvChannel(int channel) { |
2304 // Configure to use external transport, like our default channel. | 2310 // Configure to use external transport. |
2305 if (engine()->voe()->network()->RegisterExternalTransport( | 2311 if (engine()->voe()->network()->RegisterExternalTransport( |
2306 channel, *this) == -1) { | 2312 channel, *this) == -1) { |
2307 LOG_RTCERR2(SetExternalTransport, channel, this); | 2313 LOG_RTCERR2(SetExternalTransport, channel, this); |
2308 return false; | 2314 return false; |
2309 } | 2315 } |
2310 | 2316 |
2311 // Use the same SSRC as our default channel (so the RTCP reports are correct). | 2317 if (!SetRecvOptions(channel)) { |
2318 return false; | |
2319 } | |
2320 | |
2321 // Use the same SSRC as our default (send) channel, so the RTCP reports are | |
2322 // correct. | |
2312 unsigned int send_ssrc = 0; | 2323 unsigned int send_ssrc = 0; |
2313 webrtc::VoERTP_RTCP* rtp = engine()->voe()->rtp(); | 2324 webrtc::VoERTP_RTCP* rtp = engine()->voe()->rtp(); |
2314 if (rtp->GetLocalSSRC(voe_channel(), send_ssrc) == -1) { | 2325 if (rtp->GetLocalSSRC(voe_channel(), send_ssrc) == -1) { |
2315 LOG_RTCERR1(GetSendSSRC, channel); | 2326 LOG_RTCERR1(GetSendSSRC, channel); |
2316 return false; | 2327 return false; |
2317 } | 2328 } |
2318 if (rtp->SetLocalSSRC(channel, send_ssrc) == -1) { | 2329 if (rtp->SetLocalSSRC(channel, send_ssrc) == -1) { |
2319 LOG_RTCERR1(SetSendSSRC, channel); | 2330 LOG_RTCERR1(SetSendSSRC, channel); |
2320 return false; | 2331 return false; |
2321 } | 2332 } |
2322 | 2333 |
2323 // Associate receive channel to default channel (so the receive channel can | 2334 // Associate receive channel to default send channel (so the receive channel |
2324 // obtain RTT from the send channel) | 2335 // can obtain RTT from the send channel) |
2325 engine()->voe()->base()->AssociateSendChannel(channel, voe_channel()); | 2336 engine()->voe()->base()->AssociateSendChannel(channel, voe_channel()); |
2326 LOG(LS_INFO) << "VoiceEngine channel #" | 2337 LOG(LS_INFO) << "VoiceEngine channel #" |
2327 << channel << " is associated with channel #" | 2338 << channel << " is associated with channel #" |
2328 << voe_channel() << "."; | 2339 << voe_channel() << "."; |
2329 | 2340 |
2330 // Use the same recv payload types as our default channel. | 2341 // Turn off all supported codecs. |
pthatcher1
2015/10/02 02:33:30
I like this in a helper method. But instead "Rese
the sun
2015/10/02 11:34:20
Personally I have a problem with "helper" methods.
| |
2331 ResetRecvCodecs(channel); | 2342 int ncodecs = engine()->voe()->codec()->NumOfCodecs(); |
2332 if (!recv_codecs_.empty()) { | 2343 for (int i = 0; i < ncodecs; ++i) { |
2333 for (const auto& codec : recv_codecs_) { | 2344 webrtc::CodecInst voe_codec; |
2334 webrtc::CodecInst voe_codec; | 2345 if (engine()->voe()->codec()->GetCodec(i, voe_codec) != -1) { |
2335 if (engine()->FindWebRtcCodec(codec, &voe_codec)) { | 2346 voe_codec.pltype = -1; |
2336 voe_codec.pltype = codec.id; | 2347 if (engine()->voe()->codec()->SetRecPayloadType( |
2337 voe_codec.rate = 0; // Needed to make GetRecPayloadType work for ISAC | 2348 channel, voe_codec) == -1) { |
2338 if (engine()->voe()->codec()->GetRecPayloadType( | 2349 LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec)); |
2339 voe_channel(), voe_codec) != -1) { | 2350 return false; |
2340 if (engine()->voe()->codec()->SetRecPayloadType( | |
2341 channel, voe_codec) == -1) { | |
2342 LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec)); | |
2343 return false; | |
2344 } | |
2345 } | |
2346 } | 2351 } |
2347 } | 2352 } |
2348 } | 2353 } |
2349 | 2354 |
2350 if (InConferenceMode()) { | 2355 // Only enable those configured for this channel. |
2351 // To be in par with the video, voe_channel() is not used for receiving in | 2356 for (const auto& codec : recv_codecs_) { |
2352 // a conference call. | 2357 webrtc::CodecInst voe_codec; |
2353 if (receive_channels_.empty() && default_receive_ssrc_ == 0 && playout_) { | 2358 if (engine()->FindWebRtcCodec(codec, &voe_codec)) { |
2354 // This is the first stream in a multi user meeting. We can now | 2359 voe_codec.pltype = codec.id; |
pthatcher1
2015/10/02 02:33:31
Why did you remove .rate = 0?
the sun
2015/10/02 11:34:20
It said in a comment: "// Needed to make GetRecPay
| |
2355 // disable playback of the default stream. This since the default | 2360 if (engine()->voe()->codec()->SetRecPayloadType( |
2356 // stream will probably have received some initial packets before | 2361 channel, voe_codec) == -1) { |
2357 // the new stream was added. This will mean that the CN state from | 2362 LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec)); |
2358 // the default channel will be mixed in with the other streams | 2363 return false; |
2359 // throughout the whole meeting, which might be disturbing. | 2364 } |
2360 LOG(LS_INFO) << "Disabling playback on the default voice channel"; | |
2361 SetPlayout(voe_channel(), false); | |
2362 } | 2365 } |
2363 } | 2366 } |
2367 | |
2364 SetNack(channel, nack_enabled_); | 2368 SetNack(channel, nack_enabled_); |
2365 | 2369 |
2366 // Set RTP header extension for the new channel. | 2370 // Set RTP header extension for the new channel. |
2367 if (!SetChannelRecvRtpHeaderExtensions(channel, receive_extensions_)) { | 2371 if (!SetChannelRecvRtpHeaderExtensions(channel, receive_extensions_)) { |
2368 return false; | 2372 return false; |
2369 } | 2373 } |
2370 | 2374 |
2371 return SetPlayout(channel, playout_); | 2375 return SetPlayout(channel, playout_); |
2372 } | 2376 } |
2373 | 2377 |
2374 bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32 ssrc) { | 2378 bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32 ssrc) { |
2375 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 2379 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
2376 rtc::CritScope lock(&receive_channels_cs_); | 2380 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; |
2381 | |
2377 ChannelMap::iterator it = receive_channels_.find(ssrc); | 2382 ChannelMap::iterator it = receive_channels_.find(ssrc); |
2378 if (it == receive_channels_.end()) { | 2383 if (it == receive_channels_.end()) { |
2379 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc | 2384 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc |
2380 << " which doesn't exist."; | 2385 << " which doesn't exist."; |
2381 return false; | 2386 return false; |
2382 } | 2387 } |
2383 | 2388 |
2384 RemoveAudioReceiveStream(ssrc); | 2389 RemoveAudioReceiveStream(ssrc); |
2385 receive_stream_params_.erase(ssrc); | 2390 receive_stream_params_.erase(ssrc); |
2386 | 2391 |
2387 // Delete the WebRtcVoiceChannelRenderer object connected to the channel, this | 2392 // Delete the WebRtcVoiceChannelRenderer object connected to the channel, this |
2388 // will disconnect the audio renderer with the receive channel. | 2393 // will disconnect the audio renderer with the receive channel. |
2389 // Cache the channel before the deletion. | 2394 // Cache the channel before the deletion. |
2390 const int channel = it->second->channel(); | 2395 const int channel = it->second->channel(); |
2391 delete it->second; | 2396 delete it->second; |
2392 receive_channels_.erase(it); | 2397 receive_channels_.erase(it); |
2393 | 2398 |
2394 if (ssrc == default_receive_ssrc_) { | 2399 // Deregister default channel, if that's the one being destroyed. |
2395 RTC_DCHECK(IsDefaultChannel(channel)); | 2400 if (-1 != default_recv_channel_id_ && ssrc == default_recv_ssrc_) { |
2396 // Recycle the default channel is for recv stream. | 2401 RTC_DCHECK(channel == default_recv_channel_id_); |
2397 if (playout_) | 2402 default_recv_ssrc_ = 0; |
2398 SetPlayout(voe_channel(), false); | 2403 default_recv_channel_id_ = -1; |
2399 | |
2400 default_receive_ssrc_ = 0; | |
2401 return true; | |
2402 } | 2404 } |
2403 | 2405 |
2404 LOG(LS_INFO) << "Removing audio stream " << ssrc | 2406 LOG(LS_INFO) << "Removing audio stream " << ssrc |
2405 << " with VoiceEngine channel #" << channel << "."; | 2407 << " with VoiceEngine channel #" << channel << "."; |
2406 if (!DeleteChannel(channel)) | 2408 return DeleteChannel(channel); |
2407 return false; | |
2408 | |
2409 bool enable_default_channel_playout = false; | |
2410 if (receive_channels_.empty()) { | |
2411 // The last stream was removed. We can now enable the default | |
2412 // channel for new channels to be played out immediately without | |
2413 // waiting for AddStream messages. | |
2414 // We do this for both conference mode and non-conference mode. | |
2415 // TODO(oja): Does the default channel still have it's CN state? | |
2416 enable_default_channel_playout = true; | |
2417 } | |
2418 if (!InConferenceMode() && receive_channels_.size() == 1 && | |
2419 default_receive_ssrc_ != 0) { | |
2420 // Only the default channel is active, enable the playout on default | |
2421 // channel. | |
2422 enable_default_channel_playout = true; | |
2423 } | |
2424 if (enable_default_channel_playout && playout_) { | |
2425 LOG(LS_INFO) << "Enabling playback on the default voice channel"; | |
2426 SetPlayout(voe_channel(), true); | |
2427 } | |
2428 | |
2429 return true; | |
2430 } | 2409 } |
2431 | 2410 |
2432 bool WebRtcVoiceMediaChannel::SetRemoteRenderer(uint32 ssrc, | 2411 bool WebRtcVoiceMediaChannel::SetRemoteRenderer(uint32 ssrc, |
2433 AudioRenderer* renderer) { | 2412 AudioRenderer* renderer) { |
2413 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | |
2434 ChannelMap::iterator it = receive_channels_.find(ssrc); | 2414 ChannelMap::iterator it = receive_channels_.find(ssrc); |
2435 if (it == receive_channels_.end()) { | 2415 if (it == receive_channels_.end()) { |
2436 if (renderer) { | 2416 if (renderer) { |
2437 // Return an error if trying to set a valid renderer with an invalid ssrc. | 2417 // Return an error if trying to set a valid renderer with an invalid ssrc. |
2438 LOG(LS_ERROR) << "SetRemoteRenderer failed with ssrc "<< ssrc; | 2418 LOG(LS_ERROR) << "SetRemoteRenderer failed with ssrc "<< ssrc; |
2439 return false; | 2419 return false; |
2440 } | 2420 } |
2441 | 2421 |
2442 // The channel likely has gone away, do nothing. | 2422 // The channel likely has gone away, do nothing. |
2443 return true; | 2423 return true; |
(...skipping 24 matching lines...) Expand all Loading... | |
2468 if (renderer) | 2448 if (renderer) |
2469 it->second->Start(renderer); | 2449 it->second->Start(renderer); |
2470 else | 2450 else |
2471 it->second->Stop(); | 2451 it->second->Stop(); |
2472 | 2452 |
2473 return true; | 2453 return true; |
2474 } | 2454 } |
2475 | 2455 |
2476 bool WebRtcVoiceMediaChannel::GetActiveStreams( | 2456 bool WebRtcVoiceMediaChannel::GetActiveStreams( |
2477 AudioInfo::StreamList* actives) { | 2457 AudioInfo::StreamList* actives) { |
2478 // In conference mode, the default channel should not be in | 2458 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
2479 // |receive_channels_|. | |
2480 actives->clear(); | 2459 actives->clear(); |
2481 for (const auto& ch : receive_channels_) { | 2460 for (const auto& ch : receive_channels_) { |
2482 int level = GetOutputLevel(ch.second->channel()); | 2461 int level = GetOutputLevel(ch.second->channel()); |
2483 if (level > 0) { | 2462 if (level > 0) { |
2484 actives->push_back(std::make_pair(ch.first, level)); | 2463 actives->push_back(std::make_pair(ch.first, level)); |
2485 } | 2464 } |
2486 } | 2465 } |
2487 return true; | 2466 return true; |
2488 } | 2467 } |
2489 | 2468 |
2490 int WebRtcVoiceMediaChannel::GetOutputLevel() { | 2469 int WebRtcVoiceMediaChannel::GetOutputLevel() { |
2491 // return the highest output level of all streams | 2470 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
2492 int highest = GetOutputLevel(voe_channel()); | 2471 int highest = 0; |
2493 for (const auto& ch : receive_channels_) { | 2472 for (const auto& ch : receive_channels_) { |
2494 int level = GetOutputLevel(ch.second->channel()); | 2473 highest = std::max(GetOutputLevel(ch.second->channel()), highest); |
2495 highest = std::max(level, highest); | |
2496 } | 2474 } |
2497 return highest; | 2475 return highest; |
2498 } | 2476 } |
2499 | 2477 |
2500 int WebRtcVoiceMediaChannel::GetTimeSinceLastTyping() { | 2478 int WebRtcVoiceMediaChannel::GetTimeSinceLastTyping() { |
2501 int ret; | 2479 int ret; |
2502 if (engine()->voe()->processing()->TimeSinceLastTyping(ret) == -1) { | 2480 if (engine()->voe()->processing()->TimeSinceLastTyping(ret) == -1) { |
2503 // In case of error, log the info and continue | 2481 // In case of error, log the info and continue |
2504 LOG_RTCERR0(TimeSinceLastTyping); | 2482 LOG_RTCERR0(TimeSinceLastTyping); |
2505 ret = -1; | 2483 ret = -1; |
(...skipping 11 matching lines...) Expand all Loading... | |
2517 reporting_threshold, penalty_decay, type_event_delay) == -1) { | 2495 reporting_threshold, penalty_decay, type_event_delay) == -1) { |
2518 // In case of error, log the info and continue | 2496 // In case of error, log the info and continue |
2519 LOG_RTCERR5(SetTypingDetectionParameters, time_window, | 2497 LOG_RTCERR5(SetTypingDetectionParameters, time_window, |
2520 cost_per_typing, reporting_threshold, penalty_decay, | 2498 cost_per_typing, reporting_threshold, penalty_decay, |
2521 type_event_delay); | 2499 type_event_delay); |
2522 } | 2500 } |
2523 } | 2501 } |
2524 | 2502 |
2525 bool WebRtcVoiceMediaChannel::SetOutputScaling( | 2503 bool WebRtcVoiceMediaChannel::SetOutputScaling( |
2526 uint32 ssrc, double left, double right) { | 2504 uint32 ssrc, double left, double right) { |
2527 rtc::CritScope lock(&receive_channels_cs_); | 2505 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
2528 // Collect the channels to scale the output volume. | 2506 // Collect channels to scale output volume for (ssrc == 0 means all channels). |
pthatcher1
2015/10/02 02:33:31
This "ssrc == 0 means all" was just a GTP thing.
the sun
2015/10/02 11:34:20
But we still need to support "ssrc == 0 means defa
| |
2529 std::vector<int> channels; | 2507 std::vector<int> channels; |
2530 if (0 == ssrc) { // Collect all channels, including the default one. | 2508 for (const auto& ch : receive_channels_) { |
2531 // Default channel is not in receive_channels_ if it is not being used for | 2509 if (0 == ssrc || ch.first == ssrc) { |
2532 // playout. | |
2533 if (default_receive_ssrc_ == 0) | |
2534 channels.push_back(voe_channel()); | |
2535 for (const auto& ch : receive_channels_) { | |
2536 channels.push_back(ch.second->channel()); | 2510 channels.push_back(ch.second->channel()); |
2537 } | 2511 } |
2538 } else { // Collect only the channel of the specified ssrc. | 2512 } |
2539 int channel = GetReceiveChannelNum(ssrc); | 2513 if (0 != ssrc && channels.empty()) { |
2540 if (-1 == channel) { | 2514 LOG(LS_WARNING) << "Cannot find channel for ssrc:" << ssrc; |
2541 LOG(LS_WARNING) << "Cannot find channel for ssrc:" << ssrc; | 2515 return false; |
2542 return false; | |
2543 } | |
2544 channels.push_back(channel); | |
2545 } | 2516 } |
2546 | 2517 |
2547 // Scale the output volume for the collected channels. We first normalize to | 2518 // Scale the output volume for the collected channels. We first normalize to |
2548 // scale the volume and then set the left and right pan. | 2519 // scale the volume and then set the left and right pan. |
2549 float scale = static_cast<float>(std::max(left, right)); | 2520 float scale = static_cast<float>(std::max(left, right)); |
2550 if (scale > 0.0001f) { | 2521 if (scale > 0.0001f) { |
2551 left /= scale; | 2522 left /= scale; |
2552 right /= scale; | 2523 right /= scale; |
2553 } | 2524 } |
2554 for (int ch_id : channels) { | 2525 for (int ch_id : channels) { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2621 } | 2592 } |
2622 } | 2593 } |
2623 | 2594 |
2624 return true; | 2595 return true; |
2625 } | 2596 } |
2626 | 2597 |
2627 void WebRtcVoiceMediaChannel::OnPacketReceived( | 2598 void WebRtcVoiceMediaChannel::OnPacketReceived( |
2628 rtc::Buffer* packet, const rtc::PacketTime& packet_time) { | 2599 rtc::Buffer* packet, const rtc::PacketTime& packet_time) { |
2629 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 2600 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
2630 | 2601 |
2631 // Forward packet to Call as well. | 2602 uint32 ssrc = 0; |
2603 if (!GetRtpSsrc(packet->data(), packet->size(), &ssrc)) { | |
2604 return; | |
2605 } | |
2606 | |
2607 if (receive_channels_.empty()) { | |
2608 // Create new channel, which will be the default receive channel. | |
2609 StreamParams sp; | |
2610 sp.ssrcs.push_back(ssrc); | |
2611 LOG(LS_INFO) << "Creating default receive stream for SSRC=" << ssrc << "."; | |
2612 if (!AddRecvStream(sp)) { | |
2613 LOG(LS_WARNING) << "Could not create default receive stream."; | |
2614 return; | |
2615 } | |
2616 default_recv_ssrc_ = ssrc; | |
2617 default_recv_channel_id_ = receive_channels_[ssrc]->channel(); | |
pthatcher1
2015/10/02 02:33:30
Why not just call GetRecvChannelNum?
the sun
2015/10/02 11:34:19
Done.
| |
2618 RTC_DCHECK(-1 != default_recv_channel_id_); | |
2619 } | |
2620 | |
2621 // Forward packet to Call. If the SSRC is unknown we'll return after this. | |
2632 const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp, | 2622 const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp, |
2633 packet_time.not_before); | 2623 packet_time.not_before); |
2634 call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO, | 2624 webrtc::PacketReceiver::DeliveryStatus delivery_result = |
2635 reinterpret_cast<const uint8_t*>(packet->data()), packet->size(), | 2625 call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO, |
2636 webrtc_packet_time); | 2626 reinterpret_cast<const uint8_t*>(packet->data()), packet->size(), |
2627 webrtc_packet_time); | |
2628 if (webrtc::PacketReceiver::DELIVERY_OK != delivery_result) { | |
2629 return; | |
2630 } | |
2637 | 2631 |
2638 // Pick which channel to send this packet to. If this packet doesn't match | 2632 // Find the channel to send this packet to. It must exist since webrtc::Call |
2639 // any multiplexed streams, just send it to the default channel. Otherwise, | 2633 // was able to demux the packet. |
2640 // send it to the specific decoder instance for that stream. | 2634 int channel = GetReceiveChannelNum(ssrc); |
2641 int which_channel = | 2635 RTC_DCHECK(channel != -1); |
2642 GetReceiveChannelNum(ParseSsrc(packet->data(), packet->size(), false)); | |
2643 if (which_channel == -1) { | |
2644 which_channel = voe_channel(); | |
2645 } | |
2646 | 2636 |
2647 // Pass it off to the decoder. | 2637 // Pass it off to the decoder. |
2648 engine()->voe()->network()->ReceivedRTPPacket( | 2638 engine()->voe()->network()->ReceivedRTPPacket( |
2649 which_channel, packet->data(), packet->size(), | 2639 channel, packet->data(), packet->size(), webrtc_packet_time); |
2650 webrtc::PacketTime(packet_time.timestamp, packet_time.not_before)); | |
2651 } | 2640 } |
2652 | 2641 |
2653 void WebRtcVoiceMediaChannel::OnRtcpReceived( | 2642 void WebRtcVoiceMediaChannel::OnRtcpReceived( |
2654 rtc::Buffer* packet, const rtc::PacketTime& packet_time) { | 2643 rtc::Buffer* packet, const rtc::PacketTime& packet_time) { |
2655 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 2644 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
2656 | 2645 |
2657 // Forward packet to Call as well. | 2646 // Forward packet to Call as well. |
2658 const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp, | 2647 const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp, |
2659 packet_time.not_before); | 2648 packet_time.not_before); |
2660 call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO, | 2649 call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO, |
2661 reinterpret_cast<const uint8_t*>(packet->data()), packet->size(), | 2650 reinterpret_cast<const uint8_t*>(packet->data()), packet->size(), |
2662 webrtc_packet_time); | 2651 webrtc_packet_time); |
2663 | 2652 |
2664 // Sending channels need all RTCP packets with feedback information. | 2653 // Sending channels need all RTCP packets with feedback information. |
2665 // Even sender reports can contain attached report blocks. | 2654 // Even sender reports can contain attached report blocks. |
2666 // Receiving channels need sender reports in order to create | 2655 // Receiving channels need sender reports in order to create |
2667 // correct receiver reports. | 2656 // correct receiver reports. |
2668 int type = 0; | 2657 int type = 0; |
2669 if (!GetRtcpType(packet->data(), packet->size(), &type)) { | 2658 if (!GetRtcpType(packet->data(), packet->size(), &type)) { |
2670 LOG(LS_WARNING) << "Failed to parse type from received RTCP packet"; | 2659 LOG(LS_WARNING) << "Failed to parse type from received RTCP packet"; |
2671 return; | 2660 return; |
2672 } | 2661 } |
2673 | 2662 |
2674 // If it is a sender report, find the channel that is listening. | 2663 // If it is a sender report, find the receive channel that is listening. |
2675 bool has_sent_to_default_channel = false; | |
2676 if (type == kRtcpTypeSR) { | 2664 if (type == kRtcpTypeSR) { |
2677 int which_channel = | 2665 uint32 ssrc = 0; |
2678 GetReceiveChannelNum(ParseSsrc(packet->data(), packet->size(), true)); | 2666 if (!GetRtcpSsrc(packet->data(), packet->size(), &ssrc)) { |
2679 if (which_channel != -1) { | 2667 return; |
2668 } | |
2669 int channel = GetReceiveChannelNum(ssrc); | |
pthatcher1
2015/10/02 02:33:31
Should this be recv_channel_id to be consistent?
the sun
2015/10/02 11:34:20
Done.
| |
2670 if (channel != -1) { | |
2680 engine()->voe()->network()->ReceivedRTCPPacket( | 2671 engine()->voe()->network()->ReceivedRTCPPacket( |
2681 which_channel, packet->data(), packet->size()); | 2672 channel, packet->data(), packet->size()); |
2682 | |
2683 if (IsDefaultChannel(which_channel)) | |
2684 has_sent_to_default_channel = true; | |
2685 } | 2673 } |
2686 } | 2674 } |
2687 | 2675 |
2688 // SR may continue RR and any RR entry may correspond to any one of the send | 2676 // SR may continue RR and any RR entry may correspond to any one of the send |
2689 // channels. So all RTCP packets must be forwarded all send channels. VoE | 2677 // channels. So all RTCP packets must be forwarded all send channels. VoE |
2690 // will filter out RR internally. | 2678 // will filter out RR internally. |
2691 for (const auto& ch : send_channels_) { | 2679 for (const auto& ch : send_channels_) { |
2692 // Make sure not sending the same packet to default channel more than once. | |
2693 if (IsDefaultChannel(ch.second->channel()) && | |
2694 has_sent_to_default_channel) | |
2695 continue; | |
2696 | |
2697 engine()->voe()->network()->ReceivedRTCPPacket( | 2680 engine()->voe()->network()->ReceivedRTCPPacket( |
2698 ch.second->channel(), packet->data(), packet->size()); | 2681 ch.second->channel(), packet->data(), packet->size()); |
2699 } | 2682 } |
2700 } | 2683 } |
2701 | 2684 |
2702 bool WebRtcVoiceMediaChannel::MuteStream(uint32 ssrc, bool muted) { | 2685 bool WebRtcVoiceMediaChannel::MuteStream(uint32 ssrc, bool muted) { |
2703 int channel = (ssrc == 0) ? voe_channel() : GetSendChannelNum(ssrc); | 2686 int channel = (ssrc == 0) ? voe_channel() : GetSendChannelNum(ssrc); |
2704 if (channel == -1) { | 2687 if (channel == -1) { |
2705 LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use."; | 2688 LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use."; |
2706 return false; | 2689 return false; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2777 LOG(LS_INFO) << "Failed to set codec " << codec.plname | 2760 LOG(LS_INFO) << "Failed to set codec " << codec.plname |
2778 << " to bitrate " << bps << " bps" | 2761 << " to bitrate " << bps << " bps" |
2779 << ", requires at least " << codec.rate << " bps."; | 2762 << ", requires at least " << codec.rate << " bps."; |
2780 return false; | 2763 return false; |
2781 } | 2764 } |
2782 return true; | 2765 return true; |
2783 } | 2766 } |
2784 } | 2767 } |
2785 | 2768 |
2786 bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) { | 2769 bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) { |
2770 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | |
2771 | |
2787 bool echo_metrics_on = false; | 2772 bool echo_metrics_on = false; |
2788 // These can take on valid negative values, so use the lowest possible level | 2773 // These can take on valid negative values, so use the lowest possible level |
2789 // as default rather than -1. | 2774 // as default rather than -1. |
2790 int echo_return_loss = -100; | 2775 int echo_return_loss = -100; |
2791 int echo_return_loss_enhancement = -100; | 2776 int echo_return_loss_enhancement = -100; |
2792 // These can also be negative, but in practice -1 is only used to signal | 2777 // These can also be negative, but in practice -1 is only used to signal |
2793 // insufficient data, since the resolution is limited to multiples of 4 ms. | 2778 // insufficient data, since the resolution is limited to multiples of 4 ms. |
2794 int echo_delay_median_ms = -1; | 2779 int echo_delay_median_ms = -1; |
2795 int echo_delay_std_ms = -1; | 2780 int echo_delay_std_ms = -1; |
2796 if (engine()->voe()->processing()->GetEcMetricsStatus( | 2781 if (engine()->voe()->processing()->GetEcMetricsStatus( |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2878 sinfo.echo_return_loss_enhancement = echo_return_loss_enhancement; | 2863 sinfo.echo_return_loss_enhancement = echo_return_loss_enhancement; |
2879 sinfo.echo_delay_median_ms = echo_delay_median_ms; | 2864 sinfo.echo_delay_median_ms = echo_delay_median_ms; |
2880 sinfo.echo_delay_std_ms = echo_delay_std_ms; | 2865 sinfo.echo_delay_std_ms = echo_delay_std_ms; |
2881 // TODO(ajm): Re-enable this metric once we have a reliable implementation. | 2866 // TODO(ajm): Re-enable this metric once we have a reliable implementation. |
2882 sinfo.aec_quality_min = -1; | 2867 sinfo.aec_quality_min = -1; |
2883 sinfo.typing_noise_detected = typing_noise_detected_; | 2868 sinfo.typing_noise_detected = typing_noise_detected_; |
2884 | 2869 |
2885 info->senders.push_back(sinfo); | 2870 info->senders.push_back(sinfo); |
2886 } | 2871 } |
2887 | 2872 |
2888 // Build the list of receivers, one for each receiving channel, or 1 in | 2873 // Get the SSRC and stats for each receiver. |
2889 // a 1:1 call. | |
2890 std::vector<int> channels; | |
2891 for (const auto& ch : receive_channels_) { | 2874 for (const auto& ch : receive_channels_) { |
2892 channels.push_back(ch.second->channel()); | 2875 int ch_id = ch.second->channel(); |
2893 } | |
2894 if (channels.empty()) { | |
2895 channels.push_back(voe_channel()); | |
2896 } | |
2897 | |
2898 // Get the SSRC and stats for each receiver, based on our own calculations. | |
2899 for (int ch_id : channels) { | |
2900 memset(&cs, 0, sizeof(cs)); | 2876 memset(&cs, 0, sizeof(cs)); |
2901 if (engine()->voe()->rtp()->GetRemoteSSRC(ch_id, ssrc) != -1 && | 2877 if (engine()->voe()->rtp()->GetRemoteSSRC(ch_id, ssrc) != -1 && |
2902 engine()->voe()->rtp()->GetRTCPStatistics(ch_id, cs) != -1 && | 2878 engine()->voe()->rtp()->GetRTCPStatistics(ch_id, cs) != -1 && |
2903 engine()->voe()->codec()->GetRecCodec(ch_id, codec) != -1) { | 2879 engine()->voe()->codec()->GetRecCodec(ch_id, codec) != -1) { |
2904 VoiceReceiverInfo rinfo; | 2880 VoiceReceiverInfo rinfo; |
2905 rinfo.add_ssrc(ssrc); | 2881 rinfo.add_ssrc(ssrc); |
2906 rinfo.bytes_rcvd = cs.bytesReceived; | 2882 rinfo.bytes_rcvd = cs.bytesReceived; |
2907 rinfo.packets_rcvd = cs.packetsReceived; | 2883 rinfo.packets_rcvd = cs.packetsReceived; |
2908 // The next four fields are from the most recently sent RTCP report. | 2884 // The next four fields are from the most recently sent RTCP report. |
2909 // Convert Q8 to floating point. | 2885 // Convert Q8 to floating point. |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2964 rinfo.audio_level = (engine()->voe()->volume()-> | 2940 rinfo.audio_level = (engine()->voe()->volume()-> |
2965 GetSpeechOutputLevelFullRange(ch_id, level) != -1) ? level : -1; | 2941 GetSpeechOutputLevelFullRange(ch_id, level) != -1) ? level : -1; |
2966 info->receivers.push_back(rinfo); | 2942 info->receivers.push_back(rinfo); |
2967 } | 2943 } |
2968 } | 2944 } |
2969 | 2945 |
2970 return true; | 2946 return true; |
2971 } | 2947 } |
2972 | 2948 |
2973 bool WebRtcVoiceMediaChannel::FindSsrc(int channel_num, uint32* ssrc) { | 2949 bool WebRtcVoiceMediaChannel::FindSsrc(int channel_num, uint32* ssrc) { |
2974 rtc::CritScope lock(&receive_channels_cs_); | 2950 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
pthatcher1
2015/10/02 02:33:31
This is called by WebRtcVoiceEngine::CallbackOnErr
the sun
2015/10/02 11:34:20
Good point. Actually, AFAICT VoE only calls Callba
| |
2975 RTC_DCHECK(ssrc != NULL); | 2951 RTC_DCHECK(ssrc != NULL); |
2976 if (channel_num == -1 && send_ != SEND_NOTHING) { | 2952 if (channel_num == -1 && send_ != SEND_NOTHING) { |
2977 // Sometimes the VoiceEngine core will throw error with channel_num = -1. | 2953 // Sometimes the VoiceEngine core will throw error with channel_num = -1. |
2978 // This means the error is not limited to a specific channel. Signal the | 2954 // This means the error is not limited to a specific channel. Signal the |
2979 // message using ssrc=0. If the current channel is sending, use this | 2955 // message using ssrc=0. If the current channel is sending, use this |
2980 // channel for sending the message. | 2956 // channel for sending the message. |
2981 *ssrc = 0; | 2957 *ssrc = 0; |
2982 return true; | 2958 return true; |
2983 } else { | 2959 } else { |
2984 // Check whether this is a sending channel. | 2960 // Check whether this is a sending channel. |
(...skipping 28 matching lines...) Expand all Loading... | |
3013 } | 2989 } |
3014 } | 2990 } |
3015 | 2991 |
3016 int WebRtcVoiceMediaChannel::GetOutputLevel(int channel) { | 2992 int WebRtcVoiceMediaChannel::GetOutputLevel(int channel) { |
3017 unsigned int ulevel; | 2993 unsigned int ulevel; |
3018 int ret = | 2994 int ret = |
3019 engine()->voe()->volume()->GetSpeechOutputLevel(channel, ulevel); | 2995 engine()->voe()->volume()->GetSpeechOutputLevel(channel, ulevel); |
3020 return (ret == 0) ? static_cast<int>(ulevel) : -1; | 2996 return (ret == 0) ? static_cast<int>(ulevel) : -1; |
3021 } | 2997 } |
3022 | 2998 |
3023 int WebRtcVoiceMediaChannel::GetReceiveChannelNum(uint32 ssrc) const { | 2999 int WebRtcVoiceMediaChannel::GetReceiveChannelNum(uint32 ssrc) const { |
pthatcher1
2015/10/02 02:33:31
Can you rename this GetReceiveChannelId?
the sun
2015/10/02 11:34:19
Yes, also renamed GetSendChannelNum() similarly.
| |
3000 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | |
3024 ChannelMap::const_iterator it = receive_channels_.find(ssrc); | 3001 ChannelMap::const_iterator it = receive_channels_.find(ssrc); |
3025 if (it != receive_channels_.end()) | 3002 if (it != receive_channels_.end()) |
3026 return it->second->channel(); | 3003 return it->second->channel(); |
3027 return (ssrc == default_receive_ssrc_) ? voe_channel() : -1; | 3004 return -1; |
3028 } | 3005 } |
3029 | 3006 |
3030 int WebRtcVoiceMediaChannel::GetSendChannelNum(uint32 ssrc) const { | 3007 int WebRtcVoiceMediaChannel::GetSendChannelNum(uint32 ssrc) const { |
3031 ChannelMap::const_iterator it = send_channels_.find(ssrc); | 3008 ChannelMap::const_iterator it = send_channels_.find(ssrc); |
3032 if (it != send_channels_.end()) | 3009 if (it != send_channels_.end()) |
3033 return it->second->channel(); | 3010 return it->second->channel(); |
3034 | |
3035 return -1; | 3011 return -1; |
3036 } | 3012 } |
3037 | 3013 |
3038 bool WebRtcVoiceMediaChannel::GetRedSendCodec(const AudioCodec& red_codec, | 3014 bool WebRtcVoiceMediaChannel::GetRedSendCodec(const AudioCodec& red_codec, |
3039 const std::vector<AudioCodec>& all_codecs, webrtc::CodecInst* send_codec) { | 3015 const std::vector<AudioCodec>& all_codecs, webrtc::CodecInst* send_codec) { |
3040 // Get the RED encodings from the parameter with no name. This may | 3016 // Get the RED encodings from the parameter with no name. This may |
3041 // change based on what is discussed on the Jingle list. | 3017 // change based on what is discussed on the Jingle list. |
3042 // The encoding parameter is of the form "a/b"; we only support where | 3018 // The encoding parameter is of the form "a/b"; we only support where |
3043 // a == b. Verify this and parse out the value into red_pt. | 3019 // a == b. Verify this and parse out the value into red_pt. |
3044 // If the parameter value is absent (as it will be until we wire up the | 3020 // If the parameter value is absent (as it will be until we wire up the |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3084 LOG_RTCERR2(SetRTCPStatus, channel, 1); | 3060 LOG_RTCERR2(SetRTCPStatus, channel, 1); |
3085 return false; | 3061 return false; |
3086 } | 3062 } |
3087 // TODO(juberti): Enable VQMon and RTCP XR reports, once we know what | 3063 // TODO(juberti): Enable VQMon and RTCP XR reports, once we know what |
3088 // what we want to do with them. | 3064 // what we want to do with them. |
3089 // engine()->voe().EnableVQMon(voe_channel(), true); | 3065 // engine()->voe().EnableVQMon(voe_channel(), true); |
3090 // engine()->voe().EnableRTCP_XR(voe_channel(), true); | 3066 // engine()->voe().EnableRTCP_XR(voe_channel(), true); |
3091 return true; | 3067 return true; |
3092 } | 3068 } |
3093 | 3069 |
3094 bool WebRtcVoiceMediaChannel::ResetRecvCodecs(int channel) { | |
3095 int ncodecs = engine()->voe()->codec()->NumOfCodecs(); | |
3096 for (int i = 0; i < ncodecs; ++i) { | |
3097 webrtc::CodecInst voe_codec; | |
3098 if (engine()->voe()->codec()->GetCodec(i, voe_codec) != -1) { | |
3099 voe_codec.pltype = -1; | |
3100 if (engine()->voe()->codec()->SetRecPayloadType( | |
3101 channel, voe_codec) == -1) { | |
3102 LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec)); | |
3103 return false; | |
3104 } | |
3105 } | |
3106 } | |
3107 return true; | |
3108 } | |
3109 | |
3110 bool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) { | 3070 bool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) { |
3111 if (playout) { | 3071 if (playout) { |
3112 LOG(LS_INFO) << "Starting playout for channel #" << channel; | 3072 LOG(LS_INFO) << "Starting playout for channel #" << channel; |
3113 if (engine()->voe()->base()->StartPlayout(channel) == -1) { | 3073 if (engine()->voe()->base()->StartPlayout(channel) == -1) { |
3114 LOG_RTCERR1(StartPlayout, channel); | 3074 LOG_RTCERR1(StartPlayout, channel); |
3115 return false; | 3075 return false; |
3116 } | 3076 } |
3117 } else { | 3077 } else { |
3118 LOG(LS_INFO) << "Stopping playout for channel #" << channel; | 3078 LOG(LS_INFO) << "Stopping playout for channel #" << channel; |
3119 engine()->voe()->base()->StopPlayout(channel); | 3079 engine()->voe()->base()->StopPlayout(channel); |
3120 } | 3080 } |
3121 return true; | 3081 return true; |
3122 } | 3082 } |
3123 | 3083 |
3124 uint32 WebRtcVoiceMediaChannel::ParseSsrc(const void* data, size_t len, | |
3125 bool rtcp) { | |
3126 size_t ssrc_pos = (!rtcp) ? 8 : 4; | |
3127 uint32 ssrc = 0; | |
3128 if (len >= (ssrc_pos + sizeof(ssrc))) { | |
3129 ssrc = rtc::GetBE32(static_cast<const char*>(data) + ssrc_pos); | |
3130 } | |
3131 return ssrc; | |
3132 } | |
3133 | |
3134 // Convert VoiceEngine error code into VoiceMediaChannel::Error enum. | 3084 // Convert VoiceEngine error code into VoiceMediaChannel::Error enum. |
3135 VoiceMediaChannel::Error | 3085 VoiceMediaChannel::Error |
3136 WebRtcVoiceMediaChannel::WebRtcErrorToChannelError(int err_code) { | 3086 WebRtcVoiceMediaChannel::WebRtcErrorToChannelError(int err_code) { |
3137 switch (err_code) { | 3087 switch (err_code) { |
3138 case 0: | 3088 case 0: |
3139 return ERROR_NONE; | 3089 return ERROR_NONE; |
3140 case VE_CANNOT_START_RECORDING: | 3090 case VE_CANNOT_START_RECORDING: |
3141 case VE_MIC_VOL_ERROR: | 3091 case VE_MIC_VOL_ERROR: |
3142 case VE_GET_MIC_VOL_ERROR: | 3092 case VE_GET_MIC_VOL_ERROR: |
3143 case VE_CANNOT_ACCESS_MIC_VOL: | 3093 case VE_CANNOT_ACCESS_MIC_VOL: |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3212 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 3162 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
3213 auto stream_it = receive_streams_.find(ssrc); | 3163 auto stream_it = receive_streams_.find(ssrc); |
3214 if (stream_it != receive_streams_.end()) { | 3164 if (stream_it != receive_streams_.end()) { |
3215 call_->DestroyAudioReceiveStream(stream_it->second); | 3165 call_->DestroyAudioReceiveStream(stream_it->second); |
3216 receive_streams_.erase(stream_it); | 3166 receive_streams_.erase(stream_it); |
3217 } | 3167 } |
3218 } | 3168 } |
3219 | 3169 |
3220 bool WebRtcVoiceMediaChannel::SetRecvCodecsInternal( | 3170 bool WebRtcVoiceMediaChannel::SetRecvCodecsInternal( |
3221 const std::vector<AudioCodec>& new_codecs) { | 3171 const std::vector<AudioCodec>& new_codecs) { |
3222 for (const AudioCodec& codec : new_codecs) { | 3172 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
pthatcher1
2015/10/02 02:33:30
This is called by WebRtcVoiceMediaChannel::SetRec
the sun
2015/10/02 11:34:20
Done.
| |
3173 for (const auto& codec : new_codecs) { | |
pthatcher1
2015/10/02 02:33:30
I prefer having the (non-auto) type on for loops
the sun
2015/10/02 11:34:20
Done.
| |
3223 webrtc::CodecInst voe_codec; | 3174 webrtc::CodecInst voe_codec; |
3224 if (engine()->FindWebRtcCodec(codec, &voe_codec)) { | 3175 if (engine()->FindWebRtcCodec(codec, &voe_codec)) { |
3225 LOG(LS_INFO) << ToString(codec); | 3176 LOG(LS_INFO) << ToString(codec); |
3226 voe_codec.pltype = codec.id; | 3177 voe_codec.pltype = codec.id; |
3227 if (default_receive_ssrc_ == 0) { | |
3228 // Set the receive codecs on the default channel explicitly if the | |
3229 // default channel is not used by |receive_channels_|, this happens in | |
3230 // conference mode or in non-conference mode when there is no playout | |
3231 // channel. | |
3232 // TODO(xians): Figure out how we use the default channel in conference | |
3233 // mode. | |
3234 if (engine()->voe()->codec()->SetRecPayloadType( | |
3235 voe_channel(), voe_codec) == -1) { | |
3236 LOG_RTCERR2(SetRecPayloadType, voe_channel(), ToString(voe_codec)); | |
3237 return false; | |
3238 } | |
3239 } | |
3240 | |
3241 // Set the receive codecs on all receiving channels. | |
3242 for (const auto& ch : receive_channels_) { | 3178 for (const auto& ch : receive_channels_) { |
3243 if (engine()->voe()->codec()->SetRecPayloadType( | 3179 if (engine()->voe()->codec()->SetRecPayloadType( |
3244 ch.second->channel(), voe_codec) == -1) { | 3180 ch.second->channel(), voe_codec) == -1) { |
3245 LOG_RTCERR2(SetRecPayloadType, ch.second->channel(), | 3181 LOG_RTCERR2(SetRecPayloadType, ch.second->channel(), |
3246 ToString(voe_codec)); | 3182 ToString(voe_codec)); |
3247 return false; | 3183 return false; |
3248 } | 3184 } |
3249 } | 3185 } |
3250 } else { | 3186 } else { |
3251 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); | 3187 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); |
3252 return false; | 3188 return false; |
3253 } | 3189 } |
3254 } | 3190 } |
3255 return true; | 3191 return true; |
3256 } | 3192 } |
3257 | 3193 |
3258 } // namespace cricket | 3194 } // namespace cricket |
3259 | 3195 |
3260 #endif // HAVE_WEBRTC_VOICE | 3196 #endif // HAVE_WEBRTC_VOICE |
OLD | NEW |