| 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) { |
| 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 1204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1438 } | 1463 } |
| 1439 | 1464 |
| 1440 bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) { | 1465 bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) { |
| 1441 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 1466 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 1442 LOG(LS_INFO) << "Setting voice channel options: " | 1467 LOG(LS_INFO) << "Setting voice channel options: " |
| 1443 << options.ToString(); | 1468 << options.ToString(); |
| 1444 | 1469 |
| 1445 // Check if DSCP value is changed from previous. | 1470 // Check if DSCP value is changed from previous. |
| 1446 bool dscp_option_changed = (options_.dscp != options.dscp); | 1471 bool dscp_option_changed = (options_.dscp != options.dscp); |
| 1447 | 1472 |
| 1448 // TODO(xians): Add support to set different options for different send | |
| 1449 // streams after we support multiple APMs. | |
| 1450 | |
| 1451 // We retain all of the existing options, and apply the given ones | 1473 // We retain all of the existing options, and apply the given ones |
| 1452 // on top. This means there is no way to "clear" options such that | 1474 // on top. This means there is no way to "clear" options such that |
| 1453 // they go back to the engine default. | 1475 // they go back to the engine default. |
| 1454 options_.SetAll(options); | 1476 options_.SetAll(options); |
| 1455 | 1477 |
| 1456 if (send_ != SEND_NOTHING) { | 1478 if (send_ != SEND_NOTHING) { |
| 1457 if (!engine()->ApplyOptions(options_)) { | 1479 if (!engine()->ApplyOptions(options_)) { |
| 1458 LOG(LS_WARNING) << | 1480 LOG(LS_WARNING) << |
| 1459 "Failed to apply engine options during channel SetOptions."; | 1481 "Failed to apply engine options during channel SetOptions."; |
| 1460 return false; | 1482 return false; |
| 1461 } | 1483 } |
| 1462 } | 1484 } |
| 1463 | 1485 |
| 1464 // 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 | |
| 1466 // have the desired effect, since voice channels don't inherit options from | |
| 1467 // the media engine when those options are applied per-channel. | |
| 1468 bool rx_auto_gain_control; | |
| 1469 if (options.rx_auto_gain_control.Get(&rx_auto_gain_control)) { | |
| 1470 if (engine()->voe()->processing()->SetRxAgcStatus( | |
| 1471 voe_channel(), rx_auto_gain_control, | |
| 1472 webrtc::kAgcFixedDigital) == -1) { | |
| 1473 LOG_RTCERR1(SetRxAgcStatus, rx_auto_gain_control); | |
| 1474 return false; | |
| 1475 } else { | |
| 1476 LOG(LS_VERBOSE) << "Rx auto gain set to " << rx_auto_gain_control | |
| 1477 << " with mode " << webrtc::kAgcFixedDigital; | |
| 1478 } | |
| 1479 } | |
| 1480 if (options.rx_agc_target_dbov.IsSet() || | |
| 1481 options.rx_agc_digital_compression_gain.IsSet() || | |
| 1482 options.rx_agc_limiter.IsSet()) { | |
| 1483 webrtc::AgcConfig config; | |
| 1484 // If only some of the options are being overridden, get the current | |
| 1485 // settings for the channel and bail if they aren't available. | |
| 1486 if (!options.rx_agc_target_dbov.IsSet() || | |
| 1487 !options.rx_agc_digital_compression_gain.IsSet() || | |
| 1488 !options.rx_agc_limiter.IsSet()) { | |
| 1489 if (engine()->voe()->processing()->GetRxAgcConfig( | |
| 1490 voe_channel(), config) != 0) { | |
| 1491 LOG(LS_ERROR) << "Failed to get default rx agc configuration for " | |
| 1492 << "channel " << voe_channel() << ". Since not all rx " | |
| 1493 << "agc options are specified, unable to safely set rx " | |
| 1494 << "agc options."; | |
| 1495 return false; | |
| 1496 } | |
| 1497 } | |
| 1498 config.targetLeveldBOv = | |
| 1499 options.rx_agc_target_dbov.GetWithDefaultIfUnset( | |
| 1500 config.targetLeveldBOv); | |
| 1501 config.digitalCompressionGaindB = | |
| 1502 options.rx_agc_digital_compression_gain.GetWithDefaultIfUnset( | |
| 1503 config.digitalCompressionGaindB); | |
| 1504 config.limiterEnable = options.rx_agc_limiter.GetWithDefaultIfUnset( | |
| 1505 config.limiterEnable); | |
| 1506 if (engine()->voe()->processing()->SetRxAgcConfig( | |
| 1507 voe_channel(), config) == -1) { | |
| 1508 LOG_RTCERR4(SetRxAgcConfig, voe_channel(), config.targetLeveldBOv, | |
| 1509 config.digitalCompressionGaindB, config.limiterEnable); | |
| 1510 return false; | |
| 1511 } | |
| 1512 } | |
| 1513 if (dscp_option_changed) { | 1486 if (dscp_option_changed) { |
| 1514 rtc::DiffServCodePoint dscp = rtc::DSCP_DEFAULT; | 1487 rtc::DiffServCodePoint dscp = rtc::DSCP_DEFAULT; |
| 1515 if (options_.dscp.GetWithDefaultIfUnset(false)) | 1488 if (options_.dscp.GetWithDefaultIfUnset(false)) |
| 1516 dscp = kAudioDscpValue; | 1489 dscp = kAudioDscpValue; |
| 1517 if (MediaChannel::SetDscp(dscp) != 0) { | 1490 if (MediaChannel::SetDscp(dscp) != 0) { |
| 1518 LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel"; | 1491 LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel"; |
| 1519 } | 1492 } |
| 1520 } | 1493 } |
| 1521 | |
| 1522 RecreateAudioReceiveStreams(); | 1494 RecreateAudioReceiveStreams(); |
| 1523 | |
| 1524 LOG(LS_INFO) << "Set voice channel options. Current options: " | 1495 LOG(LS_INFO) << "Set voice channel options. Current options: " |
| 1525 << options_.ToString(); | 1496 << options_.ToString(); |
| 1526 return true; | 1497 return true; |
| 1527 } | 1498 } |
| 1528 | 1499 |
| 1529 bool WebRtcVoiceMediaChannel::SetRecvCodecs( | 1500 bool WebRtcVoiceMediaChannel::SetRecvCodecs( |
| 1530 const std::vector<AudioCodec>& codecs) { | 1501 const std::vector<AudioCodec>& codecs) { |
| 1502 // Set the payload types to be used for incoming media. |
| 1503 LOG(LS_INFO) << "Setting receive voice codecs."; |
| 1531 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 1504 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 1532 // Set the payload types to be used for incoming media. | 1505 |
| 1533 LOG(LS_INFO) << "Setting receive voice codecs:"; | 1506 if (!VerifyUniquePayloadTypes(codecs)) { |
| 1507 LOG(LS_ERROR) << "Codec payload types overlap."; |
| 1508 return false; |
| 1509 } |
| 1534 | 1510 |
| 1535 std::vector<AudioCodec> new_codecs; | 1511 std::vector<AudioCodec> new_codecs; |
| 1536 // Find all new codecs. We allow adding new codecs but don't allow changing | 1512 // 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 | 1513 // the payload type of codecs that is already configured since we might |
| 1538 // already be receiving packets with that payload type. | 1514 // already be receiving packets with that payload type. |
| 1539 for (const AudioCodec& codec : codecs) { | 1515 for (const AudioCodec& codec : codecs) { |
| 1540 AudioCodec old_codec; | 1516 AudioCodec old_codec; |
| 1541 if (FindCodec(recv_codecs_, codec, &old_codec)) { | 1517 if (FindCodec(recv_codecs_, codec, &old_codec)) { |
| 1542 if (old_codec.id != codec.id) { | 1518 if (old_codec.id != codec.id) { |
| 1543 LOG(LS_ERROR) << codec.name << " payload type changed."; | 1519 LOG(LS_ERROR) << codec.name << " payload type changed."; |
| (...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2222 if (send_channels_.empty()) | 2198 if (send_channels_.empty()) |
| 2223 ChangeSend(SEND_NOTHING); | 2199 ChangeSend(SEND_NOTHING); |
| 2224 | 2200 |
| 2225 return true; | 2201 return true; |
| 2226 } | 2202 } |
| 2227 | 2203 |
| 2228 bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) { | 2204 bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) { |
| 2229 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 2205 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 2230 LOG(LS_INFO) << "AddRecvStream: " << sp.ToString(); | 2206 LOG(LS_INFO) << "AddRecvStream: " << sp.ToString(); |
| 2231 | 2207 |
| 2232 rtc::CritScope lock(&receive_channels_cs_); | 2208 if (!ValidateStreamParams(sp)) { |
| 2233 | |
| 2234 if (!VERIFY(sp.ssrcs.size() == 1)) | |
| 2235 return false; | |
| 2236 uint32_t ssrc = sp.first_ssrc(); | |
| 2237 | |
| 2238 if (ssrc == 0) { | |
| 2239 LOG(LS_WARNING) << "AddRecvStream with 0 ssrc is not supported."; | |
| 2240 return false; | 2209 return false; |
| 2241 } | 2210 } |
| 2242 | 2211 |
| 2212 uint32_t ssrc = sp.first_ssrc(); |
| 2213 if (ssrc == 0) { |
| 2214 LOG(LS_WARNING) << "AddRecvStream with ssrc==0 is not supported."; |
| 2215 return false; |
| 2216 } |
| 2217 |
| 2218 rtc::CritScope lock(&receive_channels_cs_); |
| 2219 |
| 2243 if (receive_channels_.find(ssrc) != receive_channels_.end()) { | 2220 if (receive_channels_.find(ssrc) != receive_channels_.end()) { |
| 2244 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc; | 2221 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc; |
| 2245 return false; | 2222 return false; |
| 2246 } | 2223 } |
| 2247 | 2224 |
| 2248 RTC_DCHECK(receive_stream_params_.find(ssrc) == receive_stream_params_.end()); | 2225 RTC_DCHECK(receive_stream_params_.find(ssrc) == receive_stream_params_.end()); |
| 2249 | 2226 |
| 2250 // Reuse default channel for recv stream in non-conference mode call | 2227 // Reuse default channel for recv stream in non-conference mode call |
| 2251 // when the default channel is not being used. | 2228 // when the default channel is not being used. |
| 2252 webrtc::AudioTransport* audio_transport = | 2229 webrtc::AudioTransport* audio_transport = |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2660 // Sending channels need all RTCP packets with feedback information. | 2637 // Sending channels need all RTCP packets with feedback information. |
| 2661 // Even sender reports can contain attached report blocks. | 2638 // Even sender reports can contain attached report blocks. |
| 2662 // Receiving channels need sender reports in order to create | 2639 // Receiving channels need sender reports in order to create |
| 2663 // correct receiver reports. | 2640 // correct receiver reports. |
| 2664 int type = 0; | 2641 int type = 0; |
| 2665 if (!GetRtcpType(packet->data(), packet->size(), &type)) { | 2642 if (!GetRtcpType(packet->data(), packet->size(), &type)) { |
| 2666 LOG(LS_WARNING) << "Failed to parse type from received RTCP packet"; | 2643 LOG(LS_WARNING) << "Failed to parse type from received RTCP packet"; |
| 2667 return; | 2644 return; |
| 2668 } | 2645 } |
| 2669 | 2646 |
| 2670 // If it is a sender report, find the channel that is listening. | 2647 // If it is a sender report, find the receive channel that is listening. |
| 2671 bool has_sent_to_default_channel = false; | 2648 bool has_sent_to_default_channel = false; |
| 2672 if (type == kRtcpTypeSR) { | 2649 if (type == kRtcpTypeSR) { |
| 2673 int which_channel = | 2650 uint32_t ssrc = 0; |
| 2674 GetReceiveChannelId(ParseSsrc(packet->data(), packet->size(), true)); | 2651 if (!GetRtcpSsrc(packet->data(), packet->size(), &ssrc)) { |
| 2675 if (which_channel != -1) { | 2652 return; |
| 2653 } |
| 2654 int recv_channel_id = GetReceiveChannelId(ssrc); |
| 2655 if (recv_channel_id != -1) { |
| 2676 engine()->voe()->network()->ReceivedRTCPPacket( | 2656 engine()->voe()->network()->ReceivedRTCPPacket( |
| 2677 which_channel, packet->data(), packet->size()); | 2657 recv_channel_id, packet->data(), packet->size()); |
| 2678 | 2658 |
| 2679 if (IsDefaultChannel(which_channel)) | 2659 if (IsDefaultChannel(recv_channel_id)) |
| 2680 has_sent_to_default_channel = true; | 2660 has_sent_to_default_channel = true; |
| 2681 } | 2661 } |
| 2682 } | 2662 } |
| 2683 | 2663 |
| 2684 // SR may continue RR and any RR entry may correspond to any one of the send | 2664 // SR may continue RR and any RR entry may correspond to any one of the send |
| 2685 // channels. So all RTCP packets must be forwarded all send channels. VoE | 2665 // channels. So all RTCP packets must be forwarded all send channels. VoE |
| 2686 // will filter out RR internally. | 2666 // will filter out RR internally. |
| 2687 for (const auto& ch : send_channels_) { | 2667 for (const auto& ch : send_channels_) { |
| 2688 // Make sure not sending the same packet to default channel more than once. | 2668 // Make sure not sending the same packet to default channel more than once. |
| 2689 if (IsDefaultChannel(ch.second->channel()) && | 2669 if (IsDefaultChannel(ch.second->channel()) && |
| (...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3220 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); | 3200 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); |
| 3221 return false; | 3201 return false; |
| 3222 } | 3202 } |
| 3223 } | 3203 } |
| 3224 return true; | 3204 return true; |
| 3225 } | 3205 } |
| 3226 | 3206 |
| 3227 } // namespace cricket | 3207 } // namespace cricket |
| 3228 | 3208 |
| 3229 #endif // HAVE_WEBRTC_VOICE | 3209 #endif // HAVE_WEBRTC_VOICE |
| OLD | NEW |