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 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
141 // NOTE(ajm): Don't use hardcoded paths on platforms not explicitly specified | 141 // NOTE(ajm): Don't use hardcoded paths on platforms not explicitly specified |
142 // below. | 142 // below. |
143 #if defined(CHROMEOS) | 143 #if defined(CHROMEOS) |
144 const char kAecDumpByAudioOptionFilename[] = "/tmp/audio.aecdump"; | 144 const char kAecDumpByAudioOptionFilename[] = "/tmp/audio.aecdump"; |
145 #elif defined(ANDROID) | 145 #elif defined(ANDROID) |
146 const char kAecDumpByAudioOptionFilename[] = "/sdcard/audio.aecdump"; | 146 const char kAecDumpByAudioOptionFilename[] = "/sdcard/audio.aecdump"; |
147 #else | 147 #else |
148 const char kAecDumpByAudioOptionFilename[] = "audio.aecdump"; | 148 const char kAecDumpByAudioOptionFilename[] = "audio.aecdump"; |
149 #endif | 149 #endif |
150 | 150 |
151 bool ValidateStreamParams(const StreamParams& sp) { | |
pthatcher1
2015/10/06 18:19:52
To go along with VerifyUniquePayloadTypes, you mig
the sun
2015/10/07 10:50:25
That may not be the only thing it checks, going fo
| |
152 if (sp.ssrcs.empty()) { | |
153 LOG(LS_ERROR) << "No SSRCs in stream parameters: " << sp.ToString(); | |
154 return false; | |
155 } | |
156 if (sp.ssrcs.size() > 1) { | |
157 LOG(LS_ERROR) << "Multiple SSRCs in stream parameters: " << sp.ToString(); | |
158 return false; | |
159 } | |
160 return true; | |
161 } | |
162 | |
151 // Dumps an AudioCodec in RFC 2327-ish format. | 163 // Dumps an AudioCodec in RFC 2327-ish format. |
152 std::string ToString(const AudioCodec& codec) { | 164 std::string ToString(const AudioCodec& codec) { |
153 std::stringstream ss; | 165 std::stringstream ss; |
154 ss << codec.name << "/" << codec.clockrate << "/" << codec.channels | 166 ss << codec.name << "/" << codec.clockrate << "/" << codec.channels |
155 << " (" << codec.id << ")"; | 167 << " (" << codec.id << ")"; |
156 return ss.str(); | 168 return ss.str(); |
157 } | 169 } |
158 | 170 |
159 std::string ToString(const webrtc::CodecInst& codec) { | 171 std::string ToString(const webrtc::CodecInst& codec) { |
160 std::stringstream ss; | 172 std::stringstream ss; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
214 if (c.Matches(codec)) { | 226 if (c.Matches(codec)) { |
215 if (found_codec != NULL) { | 227 if (found_codec != NULL) { |
216 *found_codec = c; | 228 *found_codec = c; |
217 } | 229 } |
218 return true; | 230 return true; |
219 } | 231 } |
220 } | 232 } |
221 return false; | 233 return false; |
222 } | 234 } |
223 | 235 |
236 bool VerifyUniquePayloadTypes(const std::vector<AudioCodec>& codecs) { | |
237 if (codecs.empty()) { | |
238 return true; | |
239 } | |
240 std::vector<int> payload_types; | |
241 for (const AudioCodec& codec : codecs) { | |
242 payload_types.push_back(codec.id); | |
243 } | |
244 std::sort(payload_types.begin(), payload_types.end()); | |
245 auto it = std::unique(payload_types.begin(), payload_types.end()); | |
246 return it == payload_types.end(); | |
247 } | |
248 | |
224 bool IsNackEnabled(const AudioCodec& codec) { | 249 bool IsNackEnabled(const AudioCodec& codec) { |
225 return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamNack, | 250 return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamNack, |
226 kParamValueEmpty)); | 251 kParamValueEmpty)); |
227 } | 252 } |
228 | 253 |
229 int SelectPacketSize(const CodecPref& codec_pref, int ptime_ms) { | 254 int SelectPacketSize(const CodecPref& codec_pref, int ptime_ms) { |
230 int selected_packet_size_ms = codec_pref.packet_sizes_ms[0]; | 255 int selected_packet_size_ms = codec_pref.packet_sizes_ms[0]; |
231 for (int packet_size_ms : codec_pref.packet_sizes_ms) { | 256 for (int packet_size_ms : codec_pref.packet_sizes_ms) { |
232 if (packet_size_ms && packet_size_ms <= ptime_ms) { | 257 if (packet_size_ms && packet_size_ms <= ptime_ms) { |
233 selected_packet_size_ms = packet_size_ms; | 258 selected_packet_size_ms = packet_size_ms; |
(...skipping 1220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1454 options_.SetAll(options); | 1479 options_.SetAll(options); |
1455 | 1480 |
1456 if (send_ != SEND_NOTHING) { | 1481 if (send_ != SEND_NOTHING) { |
1457 if (!engine()->ApplyOptions(options_)) { | 1482 if (!engine()->ApplyOptions(options_)) { |
1458 LOG(LS_WARNING) << | 1483 LOG(LS_WARNING) << |
1459 "Failed to apply engine options during channel SetOptions."; | 1484 "Failed to apply engine options during channel SetOptions."; |
1460 return false; | 1485 return false; |
1461 } | 1486 } |
1462 } | 1487 } |
1463 | 1488 |
1489 if (!SetRecvOptions(voe_channel(), options)) { | |
1490 return false; | |
1491 } | |
1492 for (const auto& ch : receive_channels_) { | |
1493 if (!SetRecvOptions(ch.second->channel(), options)) { | |
1494 return false; | |
1495 } | |
1496 } | |
1497 if (dscp_option_changed) { | |
1498 rtc::DiffServCodePoint dscp = rtc::DSCP_DEFAULT; | |
1499 if (options_.dscp.GetWithDefaultIfUnset(false)) | |
1500 dscp = kAudioDscpValue; | |
1501 if (MediaChannel::SetDscp(dscp) != 0) { | |
1502 LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel"; | |
1503 } | |
1504 } | |
1505 RecreateAudioReceiveStreams(); | |
1506 LOG(LS_INFO) << "Set voice channel options. Current options: " | |
1507 << options_.ToString(); | |
1508 return true; | |
1509 } | |
1510 | |
1511 bool WebRtcVoiceMediaChannel::SetRecvOptions(int channel_id, | |
1512 const AudioOptions& options) { | |
1513 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | |
1514 | |
1464 // Receiver-side auto gain control happens per channel, so set it here from | 1515 // Receiver-side auto gain control happens per channel, so set it here from |
1465 // options. Note that, like conference mode, setting it on the engine won't | 1516 // options. Note that voice channels don't inherit options from the media |
1466 // have the desired effect, since voice channels don't inherit options from | 1517 // engine when those options are applied per-channel. |
1467 // the media engine when those options are applied per-channel. | |
1468 bool rx_auto_gain_control; | 1518 bool rx_auto_gain_control; |
1469 if (options.rx_auto_gain_control.Get(&rx_auto_gain_control)) { | 1519 if (options.rx_auto_gain_control.Get(&rx_auto_gain_control)) { |
1470 if (engine()->voe()->processing()->SetRxAgcStatus( | 1520 if (engine()->voe()->processing()->SetRxAgcStatus( |
1471 voe_channel(), rx_auto_gain_control, | 1521 channel_id, rx_auto_gain_control, |
1472 webrtc::kAgcFixedDigital) == -1) { | 1522 webrtc::kAgcFixedDigital) == -1) { |
1473 LOG_RTCERR1(SetRxAgcStatus, rx_auto_gain_control); | 1523 LOG_RTCERR1(SetRxAgcStatus, rx_auto_gain_control); |
1474 return false; | 1524 return false; |
1475 } else { | 1525 } else { |
1476 LOG(LS_VERBOSE) << "Rx auto gain set to " << rx_auto_gain_control | 1526 LOG(LS_VERBOSE) << "Rx auto gain set to " << rx_auto_gain_control |
1477 << " with mode " << webrtc::kAgcFixedDigital; | 1527 << " with mode " << webrtc::kAgcFixedDigital; |
1478 } | 1528 } |
1479 } | 1529 } |
1480 if (options.rx_agc_target_dbov.IsSet() || | 1530 if (options.rx_agc_target_dbov.IsSet() || |
1481 options.rx_agc_digital_compression_gain.IsSet() || | 1531 options.rx_agc_digital_compression_gain.IsSet() || |
1482 options.rx_agc_limiter.IsSet()) { | 1532 options.rx_agc_limiter.IsSet()) { |
1483 webrtc::AgcConfig config; | 1533 webrtc::AgcConfig config; |
1484 // If only some of the options are being overridden, get the current | 1534 // If only some of the options are being overridden, get the current |
1485 // settings for the channel and bail if they aren't available. | 1535 // settings for the channel and bail if they aren't available. |
1486 if (!options.rx_agc_target_dbov.IsSet() || | 1536 if (!options.rx_agc_target_dbov.IsSet() || |
1487 !options.rx_agc_digital_compression_gain.IsSet() || | 1537 !options.rx_agc_digital_compression_gain.IsSet() || |
1488 !options.rx_agc_limiter.IsSet()) { | 1538 !options.rx_agc_limiter.IsSet()) { |
1489 if (engine()->voe()->processing()->GetRxAgcConfig( | 1539 if (engine()->voe()->processing()->GetRxAgcConfig( |
1490 voe_channel(), config) != 0) { | 1540 channel_id, config) != 0) { |
1491 LOG(LS_ERROR) << "Failed to get default rx agc configuration for " | 1541 LOG(LS_ERROR) << "Failed to get default rx agc configuration for " |
1492 << "channel " << voe_channel() << ". Since not all rx " | 1542 << "channel " << channel_id << ". Since not all rx " |
1493 << "agc options are specified, unable to safely set rx " | 1543 << "agc options are specified, unable to safely set rx " |
1494 << "agc options."; | 1544 << "agc options."; |
1495 return false; | 1545 return false; |
1496 } | 1546 } |
1497 } | 1547 } |
1498 config.targetLeveldBOv = | 1548 config.targetLeveldBOv = |
1499 options.rx_agc_target_dbov.GetWithDefaultIfUnset( | 1549 options.rx_agc_target_dbov.GetWithDefaultIfUnset( |
1500 config.targetLeveldBOv); | 1550 config.targetLeveldBOv); |
1501 config.digitalCompressionGaindB = | 1551 config.digitalCompressionGaindB = |
1502 options.rx_agc_digital_compression_gain.GetWithDefaultIfUnset( | 1552 options.rx_agc_digital_compression_gain.GetWithDefaultIfUnset( |
1503 config.digitalCompressionGaindB); | 1553 config.digitalCompressionGaindB); |
1504 config.limiterEnable = options.rx_agc_limiter.GetWithDefaultIfUnset( | 1554 config.limiterEnable = options.rx_agc_limiter.GetWithDefaultIfUnset( |
1505 config.limiterEnable); | 1555 config.limiterEnable); |
1506 if (engine()->voe()->processing()->SetRxAgcConfig( | 1556 if (engine()->voe()->processing()->SetRxAgcConfig( |
1507 voe_channel(), config) == -1) { | 1557 channel_id, config) == -1) { |
1508 LOG_RTCERR4(SetRxAgcConfig, voe_channel(), config.targetLeveldBOv, | 1558 LOG_RTCERR4(SetRxAgcConfig, channel_id, config.targetLeveldBOv, |
1509 config.digitalCompressionGaindB, config.limiterEnable); | 1559 config.digitalCompressionGaindB, config.limiterEnable); |
1510 return false; | 1560 return false; |
1511 } | 1561 } |
1512 } | 1562 } |
1513 if (dscp_option_changed) { | |
1514 rtc::DiffServCodePoint dscp = rtc::DSCP_DEFAULT; | |
1515 if (options_.dscp.GetWithDefaultIfUnset(false)) | |
1516 dscp = kAudioDscpValue; | |
1517 if (MediaChannel::SetDscp(dscp) != 0) { | |
1518 LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel"; | |
1519 } | |
1520 } | |
1521 | |
1522 RecreateAudioReceiveStreams(); | |
1523 | |
1524 LOG(LS_INFO) << "Set voice channel options. Current options: " | |
1525 << options_.ToString(); | |
1526 return true; | 1563 return true; |
1527 } | 1564 } |
1528 | 1565 |
1529 bool WebRtcVoiceMediaChannel::SetRecvCodecs( | 1566 bool WebRtcVoiceMediaChannel::SetRecvCodecs( |
1530 const std::vector<AudioCodec>& codecs) { | 1567 const std::vector<AudioCodec>& codecs) { |
1568 // Set the payload types to be used for incoming media. | |
1569 LOG(LS_INFO) << "Setting receive voice codecs."; | |
1531 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 1570 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
1532 // Set the payload types to be used for incoming media. | 1571 |
1533 LOG(LS_INFO) << "Setting receive voice codecs:"; | 1572 if (!VerifyUniquePayloadTypes(codecs)) { |
1573 LOG(LS_ERROR) << "Codec payload types overlap."; | |
1574 return false; | |
1575 } | |
pthatcher1
2015/10/06 18:19:52
Can we add a unit test for this?
the sun
2015/10/07 10:50:25
There is one already: WebRtcVoiceEngineTestFake.Se
| |
1534 | 1576 |
1535 std::vector<AudioCodec> new_codecs; | 1577 std::vector<AudioCodec> new_codecs; |
1536 // Find all new codecs. We allow adding new codecs but don't allow changing | 1578 // Find all new codecs. We allow adding new codecs but don't allow changing |
1537 // the payload type of codecs that is already configured since we might | 1579 // the payload type of codecs that is already configured since we might |
1538 // already be receiving packets with that payload type. | 1580 // already be receiving packets with that payload type. |
1539 for (const AudioCodec& codec : codecs) { | 1581 for (const AudioCodec& codec : codecs) { |
1540 AudioCodec old_codec; | 1582 AudioCodec old_codec; |
1541 if (FindCodec(recv_codecs_, codec, &old_codec)) { | 1583 if (FindCodec(recv_codecs_, codec, &old_codec)) { |
1542 if (old_codec.id != codec.id) { | 1584 if (old_codec.id != codec.id) { |
1543 LOG(LS_ERROR) << codec.name << " payload type changed."; | 1585 LOG(LS_ERROR) << codec.name << " payload type changed."; |
(...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2221 if (send_channels_.empty()) | 2263 if (send_channels_.empty()) |
2222 ChangeSend(SEND_NOTHING); | 2264 ChangeSend(SEND_NOTHING); |
2223 | 2265 |
2224 return true; | 2266 return true; |
2225 } | 2267 } |
2226 | 2268 |
2227 bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) { | 2269 bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) { |
2228 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 2270 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
2229 LOG(LS_INFO) << "AddRecvStream: " << sp.ToString(); | 2271 LOG(LS_INFO) << "AddRecvStream: " << sp.ToString(); |
2230 | 2272 |
2231 rtc::CritScope lock(&receive_channels_cs_); | 2273 if (!ValidateStreamParams(sp)) { |
2232 | |
2233 if (!VERIFY(sp.ssrcs.size() == 1)) | |
2234 return false; | |
2235 uint32 ssrc = sp.first_ssrc(); | |
2236 | |
2237 if (ssrc == 0) { | |
2238 LOG(LS_WARNING) << "AddRecvStream with 0 ssrc is not supported."; | |
2239 return false; | 2274 return false; |
2240 } | 2275 } |
2241 | 2276 |
2277 uint32 ssrc = sp.first_ssrc(); | |
2278 if (ssrc == 0) { | |
2279 LOG(LS_WARNING) << "AddRecvStream with ssrc==0 is not supported."; | |
2280 return false; | |
2281 } | |
2282 | |
2283 rtc::CritScope lock(&receive_channels_cs_); | |
2284 | |
2242 if (receive_channels_.find(ssrc) != receive_channels_.end()) { | 2285 if (receive_channels_.find(ssrc) != receive_channels_.end()) { |
2243 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc; | 2286 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc; |
2244 return false; | 2287 return false; |
2245 } | 2288 } |
2246 | 2289 |
2247 RTC_DCHECK(receive_stream_params_.find(ssrc) == receive_stream_params_.end()); | 2290 RTC_DCHECK(receive_stream_params_.find(ssrc) == receive_stream_params_.end()); |
2248 | 2291 |
2249 // Reuse default channel for recv stream in non-conference mode call | 2292 // Reuse default channel for recv stream in non-conference mode call |
2250 // when the default channel is not being used. | 2293 // when the default channel is not being used. |
2251 webrtc::AudioTransport* audio_transport = | 2294 webrtc::AudioTransport* audio_transport = |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2287 | 2330 |
2288 bool WebRtcVoiceMediaChannel::ConfigureRecvChannel(int channel) { | 2331 bool WebRtcVoiceMediaChannel::ConfigureRecvChannel(int channel) { |
2289 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 2332 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
2290 // Configure to use external transport, like our default channel. | 2333 // Configure to use external transport, like our default channel. |
2291 if (engine()->voe()->network()->RegisterExternalTransport( | 2334 if (engine()->voe()->network()->RegisterExternalTransport( |
2292 channel, *this) == -1) { | 2335 channel, *this) == -1) { |
2293 LOG_RTCERR2(SetExternalTransport, channel, this); | 2336 LOG_RTCERR2(SetExternalTransport, channel, this); |
2294 return false; | 2337 return false; |
2295 } | 2338 } |
2296 | 2339 |
2340 if (!SetRecvOptions(channel, options_)) { | |
2341 return false; | |
2342 } | |
pthatcher1
2015/10/06 18:19:52
Can we add a unit test to cover that we are settin
| |
2343 | |
2297 // Use the same SSRC as our default channel (so the RTCP reports are correct). | 2344 // Use the same SSRC as our default channel (so the RTCP reports are correct). |
2298 unsigned int send_ssrc = 0; | 2345 unsigned int send_ssrc = 0; |
2299 webrtc::VoERTP_RTCP* rtp = engine()->voe()->rtp(); | 2346 webrtc::VoERTP_RTCP* rtp = engine()->voe()->rtp(); |
2300 if (rtp->GetLocalSSRC(voe_channel(), send_ssrc) == -1) { | 2347 if (rtp->GetLocalSSRC(voe_channel(), send_ssrc) == -1) { |
2301 LOG_RTCERR1(GetSendSSRC, channel); | 2348 LOG_RTCERR1(GetSendSSRC, channel); |
2302 return false; | 2349 return false; |
2303 } | 2350 } |
2304 if (rtp->SetLocalSSRC(channel, send_ssrc) == -1) { | 2351 if (rtp->SetLocalSSRC(channel, send_ssrc) == -1) { |
2305 LOG_RTCERR1(SetSendSSRC, channel); | 2352 LOG_RTCERR1(SetSendSSRC, channel); |
2306 return false; | 2353 return false; |
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2656 // Sending channels need all RTCP packets with feedback information. | 2703 // Sending channels need all RTCP packets with feedback information. |
2657 // Even sender reports can contain attached report blocks. | 2704 // Even sender reports can contain attached report blocks. |
2658 // Receiving channels need sender reports in order to create | 2705 // Receiving channels need sender reports in order to create |
2659 // correct receiver reports. | 2706 // correct receiver reports. |
2660 int type = 0; | 2707 int type = 0; |
2661 if (!GetRtcpType(packet->data(), packet->size(), &type)) { | 2708 if (!GetRtcpType(packet->data(), packet->size(), &type)) { |
2662 LOG(LS_WARNING) << "Failed to parse type from received RTCP packet"; | 2709 LOG(LS_WARNING) << "Failed to parse type from received RTCP packet"; |
2663 return; | 2710 return; |
2664 } | 2711 } |
2665 | 2712 |
2666 // If it is a sender report, find the channel that is listening. | 2713 // If it is a sender report, find the receive channel that is listening. |
2667 bool has_sent_to_default_channel = false; | 2714 bool has_sent_to_default_channel = false; |
2668 if (type == kRtcpTypeSR) { | 2715 if (type == kRtcpTypeSR) { |
2669 int which_channel = | 2716 uint32 ssrc = 0; |
2670 GetReceiveChannelId(ParseSsrc(packet->data(), packet->size(), true)); | 2717 if (!GetRtcpSsrc(packet->data(), packet->size(), &ssrc)) { |
2671 if (which_channel != -1) { | 2718 return; |
2719 } | |
2720 int recv_channel_id = GetReceiveChannelId(ssrc); | |
2721 if (recv_channel_id != -1) { | |
2672 engine()->voe()->network()->ReceivedRTCPPacket( | 2722 engine()->voe()->network()->ReceivedRTCPPacket( |
2673 which_channel, packet->data(), packet->size()); | 2723 recv_channel_id, packet->data(), packet->size()); |
2674 | 2724 |
2675 if (IsDefaultChannel(which_channel)) | 2725 if (IsDefaultChannel(recv_channel_id)) |
2676 has_sent_to_default_channel = true; | 2726 has_sent_to_default_channel = true; |
2677 } | 2727 } |
2678 } | 2728 } |
2679 | 2729 |
2680 // SR may continue RR and any RR entry may correspond to any one of the send | 2730 // SR may continue RR and any RR entry may correspond to any one of the send |
2681 // channels. So all RTCP packets must be forwarded all send channels. VoE | 2731 // channels. So all RTCP packets must be forwarded all send channels. VoE |
2682 // will filter out RR internally. | 2732 // will filter out RR internally. |
2683 for (const auto& ch : send_channels_) { | 2733 for (const auto& ch : send_channels_) { |
2684 // Make sure not sending the same packet to default channel more than once. | 2734 // Make sure not sending the same packet to default channel more than once. |
2685 if (IsDefaultChannel(ch.second->channel()) && | 2735 if (IsDefaultChannel(ch.second->channel()) && |
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3215 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); | 3265 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); |
3216 return false; | 3266 return false; |
3217 } | 3267 } |
3218 } | 3268 } |
3219 return true; | 3269 return true; |
3220 } | 3270 } |
3221 | 3271 |
3222 } // namespace cricket | 3272 } // namespace cricket |
3223 | 3273 |
3224 #endif // HAVE_WEBRTC_VOICE | 3274 #endif // HAVE_WEBRTC_VOICE |
OLD | NEW |