OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 return false; | 389 return false; |
390 } | 390 } |
391 | 391 |
392 static const AudioCodec* GetPreferredCodec( | 392 static const AudioCodec* GetPreferredCodec( |
393 const std::vector<AudioCodec>& codecs, | 393 const std::vector<AudioCodec>& codecs, |
394 webrtc::CodecInst* out) { | 394 webrtc::CodecInst* out) { |
395 RTC_DCHECK(out); | 395 RTC_DCHECK(out); |
396 // Select the preferred send codec (the first non-telephone-event/CN codec). | 396 // Select the preferred send codec (the first non-telephone-event/CN codec). |
397 for (const AudioCodec& codec : codecs) { | 397 for (const AudioCodec& codec : codecs) { |
398 if (IsCodec(codec, kDtmfCodecName) || IsCodec(codec, kCnCodecName)) { | 398 if (IsCodec(codec, kDtmfCodecName) || IsCodec(codec, kCnCodecName)) { |
399 // Skip telephone-event/CN codec, which will be handled later. | 399 // Skip telephone-event/CN codecs - they will be handled later. |
400 continue; | 400 continue; |
401 } | 401 } |
402 | 402 |
403 // We'll use the first codec in the list to actually send audio data. | 403 // We'll use the first codec in the list to actually send audio data. |
404 // Be sure to use the payload type requested by the remote side. | 404 // Be sure to use the payload type requested by the remote side. |
405 // Ignore codecs we don't know about. The negotiation step should prevent | 405 // Ignore codecs we don't know about. The negotiation step should prevent |
406 // this, but double-check to be sure. | 406 // this, but double-check to be sure. |
407 if (!ToCodecInst(codec, out)) { | 407 if (!ToCodecInst(codec, out)) { |
408 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); | 408 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); |
409 continue; | 409 continue; |
410 } | 410 } |
411 return &codec; | 411 return &codec; |
412 } | 412 } |
413 return nullptr; | 413 return nullptr; |
414 } | 414 } |
415 | 415 |
416 private: | 416 private: |
417 static const int kMaxNumPacketSize = 6; | 417 static const int kMaxNumPacketSize = 6; |
418 struct CodecPref { | 418 struct CodecPref { |
419 const char* name; | 419 const char* name; |
420 int clockrate; | 420 int clockrate; |
421 size_t channels; | 421 size_t channels; |
422 int payload_type; | 422 int payload_type; |
423 bool is_multi_rate; | 423 bool is_multi_rate; |
424 int packet_sizes_ms[kMaxNumPacketSize]; | 424 int packet_sizes_ms[kMaxNumPacketSize]; |
425 int max_bitrate_bps; | 425 int max_bitrate_bps; |
426 }; | 426 }; |
427 // Note: keep the supported packet sizes in ascending order. | 427 // Note: keep the supported packet sizes in ascending order. |
428 static const CodecPref kCodecPrefs[11]; | 428 static const CodecPref kCodecPrefs[14]; |
429 | 429 |
430 static int SelectPacketSize(const CodecPref& codec_pref, int ptime_ms) { | 430 static int SelectPacketSize(const CodecPref& codec_pref, int ptime_ms) { |
431 int selected_packet_size_ms = codec_pref.packet_sizes_ms[0]; | 431 int selected_packet_size_ms = codec_pref.packet_sizes_ms[0]; |
432 for (int packet_size_ms : codec_pref.packet_sizes_ms) { | 432 for (int packet_size_ms : codec_pref.packet_sizes_ms) { |
433 if (packet_size_ms && packet_size_ms <= ptime_ms) { | 433 if (packet_size_ms && packet_size_ms <= ptime_ms) { |
434 selected_packet_size_ms = packet_size_ms; | 434 selected_packet_size_ms = packet_size_ms; |
435 } | 435 } |
436 } | 436 } |
437 return selected_packet_size_ms; | 437 return selected_packet_size_ms; |
438 } | 438 } |
439 | 439 |
440 // Changes RTP timestamp rate of G722. This is due to the "bug" in the RFC | 440 // Changes RTP timestamp rate of G722. This is due to the "bug" in the RFC |
441 // which says that G722 should be advertised as 8 kHz although it is a 16 kHz | 441 // which says that G722 should be advertised as 8 kHz although it is a 16 kHz |
442 // codec. | 442 // codec. |
443 static void MaybeFixupG722(webrtc::CodecInst* voe_codec, int new_plfreq) { | 443 static void MaybeFixupG722(webrtc::CodecInst* voe_codec, int new_plfreq) { |
444 if (IsCodec(*voe_codec, kG722CodecName)) { | 444 if (IsCodec(*voe_codec, kG722CodecName)) { |
445 // If the ASSERT triggers, the codec definition in WebRTC VoiceEngine | 445 // If the ASSERT triggers, the codec definition in WebRTC VoiceEngine |
446 // has changed, and this special case is no longer needed. | 446 // has changed, and this special case is no longer needed. |
447 RTC_DCHECK(voe_codec->plfreq != new_plfreq); | 447 RTC_DCHECK(voe_codec->plfreq != new_plfreq); |
448 voe_codec->plfreq = new_plfreq; | 448 voe_codec->plfreq = new_plfreq; |
449 } | 449 } |
450 } | 450 } |
451 }; | 451 }; |
452 | 452 |
453 const WebRtcVoiceCodecs::CodecPref WebRtcVoiceCodecs::kCodecPrefs[11] = { | 453 const WebRtcVoiceCodecs::CodecPref WebRtcVoiceCodecs::kCodecPrefs[14] = { |
454 {kOpusCodecName, 48000, 2, 111, true, {10, 20, 40, 60}, kOpusMaxBitrate}, | 454 {kOpusCodecName, 48000, 2, 111, true, {10, 20, 40, 60}, kOpusMaxBitrate}, |
455 {kIsacCodecName, 16000, 1, 103, true, {30, 60}, kIsacMaxBitrate}, | 455 {kIsacCodecName, 16000, 1, 103, true, {30, 60}, kIsacMaxBitrate}, |
456 {kIsacCodecName, 32000, 1, 104, true, {30}, kIsacMaxBitrate}, | 456 {kIsacCodecName, 32000, 1, 104, true, {30}, kIsacMaxBitrate}, |
457 // G722 should be advertised as 8000 Hz because of the RFC "bug". | 457 // G722 should be advertised as 8000 Hz because of the RFC "bug". |
458 {kG722CodecName, 8000, 1, 9, false, {10, 20, 30, 40, 50, 60}}, | 458 {kG722CodecName, 8000, 1, 9, false, {10, 20, 30, 40, 50, 60}}, |
459 {kIlbcCodecName, 8000, 1, 102, false, {20, 30, 40, 60}}, | 459 {kIlbcCodecName, 8000, 1, 102, false, {20, 30, 40, 60}}, |
460 {kPcmuCodecName, 8000, 1, 0, false, {10, 20, 30, 40, 50, 60}}, | 460 {kPcmuCodecName, 8000, 1, 0, false, {10, 20, 30, 40, 50, 60}}, |
461 {kPcmaCodecName, 8000, 1, 8, false, {10, 20, 30, 40, 50, 60}}, | 461 {kPcmaCodecName, 8000, 1, 8, false, {10, 20, 30, 40, 50, 60}}, |
462 {kCnCodecName, 32000, 1, 106, false, {}}, | 462 {kCnCodecName, 32000, 1, 106, false, {}}, |
463 {kCnCodecName, 16000, 1, 105, false, {}}, | 463 {kCnCodecName, 16000, 1, 105, false, {}}, |
464 {kCnCodecName, 8000, 1, 13, false, {}}, | 464 {kCnCodecName, 8000, 1, 13, false, {}}, |
| 465 {kDtmfCodecName, 48000, 1, 123, false, {}}, |
| 466 {kDtmfCodecName, 32000, 1, 124, false, {}}, |
| 467 {kDtmfCodecName, 16000, 1, 125, false, {}}, |
465 {kDtmfCodecName, 8000, 1, 126, false, {}} | 468 {kDtmfCodecName, 8000, 1, 126, false, {}} |
466 }; | 469 }; |
467 } // namespace { | 470 } // namespace { |
468 | 471 |
469 bool SendCodecSpec::operator==(const SendCodecSpec& rhs) const { | 472 bool SendCodecSpec::operator==(const SendCodecSpec& rhs) const { |
470 if (nack_enabled != rhs.nack_enabled) { | 473 if (nack_enabled != rhs.nack_enabled) { |
471 return false; | 474 return false; |
472 } | 475 } |
473 if (transport_cc_enabled != rhs.transport_cc_enabled) { | 476 if (transport_cc_enabled != rhs.transport_cc_enabled) { |
474 return false; | 477 return false; |
(...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1083 RTC_DCHECK(adm_); | 1086 RTC_DCHECK(adm_); |
1084 return adm_; | 1087 return adm_; |
1085 } | 1088 } |
1086 | 1089 |
1087 AudioCodecs WebRtcVoiceEngine::CollectRecvCodecs() const { | 1090 AudioCodecs WebRtcVoiceEngine::CollectRecvCodecs() const { |
1088 PayloadTypeMapper mapper; | 1091 PayloadTypeMapper mapper; |
1089 AudioCodecs out; | 1092 AudioCodecs out; |
1090 const std::vector<webrtc::AudioCodecSpec>& specs = | 1093 const std::vector<webrtc::AudioCodecSpec>& specs = |
1091 decoder_factory_->GetSupportedDecoders(); | 1094 decoder_factory_->GetSupportedDecoders(); |
1092 | 1095 |
1093 // Only generate CN payload types for these clockrates | 1096 // Only generate CN payload types for these clockrates: |
1094 std::map<int, bool, std::greater<int>> generate_cn = {{ 8000, false }, | 1097 std::map<int, bool, std::greater<int>> generate_cn = {{ 8000, false }, |
1095 { 16000, false }, | 1098 { 16000, false }, |
1096 { 32000, false }}; | 1099 { 32000, false }}; |
| 1100 // Only generate telephone-event payload types for these clockrates: |
| 1101 std::map<int, bool, std::greater<int>> generate_dtmf = {{ 8000, false }, |
| 1102 { 16000, false }, |
| 1103 { 32000, false }, |
| 1104 { 48000, false }}; |
1097 | 1105 |
1098 auto map_format = [&mapper, &out] (const webrtc::SdpAudioFormat& format) { | 1106 auto map_format = [&mapper, &out] (const webrtc::SdpAudioFormat& format) { |
1099 rtc::Optional<AudioCodec> opt_codec = mapper.ToAudioCodec(format); | 1107 rtc::Optional<AudioCodec> opt_codec = mapper.ToAudioCodec(format); |
1100 if (!opt_codec) { | 1108 if (!opt_codec) { |
1101 LOG(LS_ERROR) << "Unable to assign payload type to format: " << format; | 1109 LOG(LS_ERROR) << "Unable to assign payload type to format: " << format; |
1102 return false; | 1110 return false; |
1103 } | 1111 } |
1104 | 1112 |
1105 auto& codec = *opt_codec; | 1113 auto& codec = *opt_codec; |
1106 if (IsCodec(codec, kOpusCodecName)) { | 1114 if (IsCodec(codec, kOpusCodecName)) { |
1107 // TODO(ossu): Set this specifically for Opus for now, until we have a | 1115 // TODO(ossu): Set this specifically for Opus for now, until we have a |
1108 // better way of dealing with rtcp-fb parameters. | 1116 // better way of dealing with rtcp-fb parameters. |
1109 codec.AddFeedbackParam( | 1117 codec.AddFeedbackParam( |
1110 FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty)); | 1118 FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty)); |
1111 } | 1119 } |
1112 out.push_back(codec); | 1120 out.push_back(codec); |
1113 return true; | 1121 return true; |
1114 }; | 1122 }; |
1115 | 1123 |
1116 for (const auto& spec : specs) { | 1124 for (const auto& spec : specs) { |
1117 if (map_format(spec.format) && spec.allow_comfort_noise) { | 1125 if (map_format(spec.format)) { |
1118 // Generate a CN entry if the decoder allows it and we support the | 1126 if (spec.allow_comfort_noise) { |
1119 // clockrate. | 1127 // Generate a CN entry if the decoder allows it and we support the |
1120 auto cn = generate_cn.find(spec.format.clockrate_hz); | 1128 // clockrate. |
1121 if (cn != generate_cn.end()) { | 1129 auto cn = generate_cn.find(spec.format.clockrate_hz); |
1122 cn->second = true; | 1130 if (cn != generate_cn.end()) { |
| 1131 cn->second = true; |
| 1132 } |
| 1133 } |
| 1134 |
| 1135 // Generate a telephone-event entry if we support the clockrate. |
| 1136 auto dtmf = generate_dtmf.find(spec.format.clockrate_hz); |
| 1137 if (dtmf != generate_dtmf.end()) { |
| 1138 dtmf->second = true; |
1123 } | 1139 } |
1124 } | 1140 } |
1125 } | 1141 } |
1126 | 1142 |
1127 // Add CN codecs after "proper" audio codecs | 1143 // Add CN codecs after "proper" audio codecs. |
1128 for (const auto& cn : generate_cn) { | 1144 for (const auto& cn : generate_cn) { |
1129 if (cn.second) { | 1145 if (cn.second) { |
1130 map_format({kCnCodecName, cn.first, 1}); | 1146 map_format({kCnCodecName, cn.first, 1}); |
1131 } | 1147 } |
1132 } | 1148 } |
1133 | 1149 |
1134 // Add telephone-event codec last | 1150 // Add telephone-event codecs last. |
1135 map_format({kDtmfCodecName, 8000, 1}); | 1151 for (const auto& dtmf : generate_dtmf) { |
| 1152 if (dtmf.second) { |
| 1153 map_format({kDtmfCodecName, dtmf.first, 1}); |
| 1154 } |
| 1155 } |
1136 | 1156 |
1137 return out; | 1157 return out; |
1138 } | 1158 } |
1139 | 1159 |
1140 class WebRtcVoiceMediaChannel::WebRtcAudioSendStream | 1160 class WebRtcVoiceMediaChannel::WebRtcAudioSendStream |
1141 : public AudioSource::Sink { | 1161 : public AudioSource::Sink { |
1142 public: | 1162 public: |
1143 WebRtcAudioSendStream(int ch, | 1163 WebRtcAudioSendStream(int ch, |
1144 webrtc::AudioTransport* voe_audio_transport, | 1164 webrtc::AudioTransport* voe_audio_transport, |
1145 uint32_t ssrc, | 1165 uint32_t ssrc, |
(...skipping 1515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2661 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 2681 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
2662 const auto it = send_streams_.find(ssrc); | 2682 const auto it = send_streams_.find(ssrc); |
2663 if (it != send_streams_.end()) { | 2683 if (it != send_streams_.end()) { |
2664 return it->second->channel(); | 2684 return it->second->channel(); |
2665 } | 2685 } |
2666 return -1; | 2686 return -1; |
2667 } | 2687 } |
2668 } // namespace cricket | 2688 } // namespace cricket |
2669 | 2689 |
2670 #endif // HAVE_WEBRTC_VOICE | 2690 #endif // HAVE_WEBRTC_VOICE |
OLD | NEW |