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 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 return false; | 417 return false; |
418 } | 418 } |
419 | 419 |
420 static const AudioCodec* GetPreferredCodec( | 420 static const AudioCodec* GetPreferredCodec( |
421 const std::vector<AudioCodec>& codecs, | 421 const std::vector<AudioCodec>& codecs, |
422 webrtc::CodecInst* out) { | 422 webrtc::CodecInst* out) { |
423 RTC_DCHECK(out); | 423 RTC_DCHECK(out); |
424 // Select the preferred send codec (the first non-telephone-event/CN codec). | 424 // Select the preferred send codec (the first non-telephone-event/CN codec). |
425 for (const AudioCodec& codec : codecs) { | 425 for (const AudioCodec& codec : codecs) { |
426 if (IsCodec(codec, kDtmfCodecName) || IsCodec(codec, kCnCodecName)) { | 426 if (IsCodec(codec, kDtmfCodecName) || IsCodec(codec, kCnCodecName)) { |
427 // Skip telephone-event/CN codec, which will be handled later. | 427 // Skip telephone-event/CN codecs - they will be handled later. |
428 continue; | 428 continue; |
429 } | 429 } |
430 | 430 |
431 // We'll use the first codec in the list to actually send audio data. | 431 // We'll use the first codec in the list to actually send audio data. |
432 // Be sure to use the payload type requested by the remote side. | 432 // Be sure to use the payload type requested by the remote side. |
433 // Ignore codecs we don't know about. The negotiation step should prevent | 433 // Ignore codecs we don't know about. The negotiation step should prevent |
434 // this, but double-check to be sure. | 434 // this, but double-check to be sure. |
435 if (!ToCodecInst(codec, out)) { | 435 if (!ToCodecInst(codec, out)) { |
436 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); | 436 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); |
437 continue; | 437 continue; |
438 } | 438 } |
439 return &codec; | 439 return &codec; |
440 } | 440 } |
441 return nullptr; | 441 return nullptr; |
442 } | 442 } |
443 | 443 |
444 private: | 444 private: |
445 static const int kMaxNumPacketSize = 6; | 445 static const int kMaxNumPacketSize = 6; |
446 struct CodecPref { | 446 struct CodecPref { |
447 const char* name; | 447 const char* name; |
448 int clockrate; | 448 int clockrate; |
449 size_t channels; | 449 size_t channels; |
450 int payload_type; | 450 int payload_type; |
451 bool is_multi_rate; | 451 bool is_multi_rate; |
452 int packet_sizes_ms[kMaxNumPacketSize]; | 452 int packet_sizes_ms[kMaxNumPacketSize]; |
453 int max_bitrate_bps; | 453 int max_bitrate_bps; |
454 }; | 454 }; |
455 // Note: keep the supported packet sizes in ascending order. | 455 // Note: keep the supported packet sizes in ascending order. |
456 static const CodecPref kCodecPrefs[11]; | 456 static const CodecPref kCodecPrefs[14]; |
457 | 457 |
458 static int SelectPacketSize(const CodecPref& codec_pref, int ptime_ms) { | 458 static int SelectPacketSize(const CodecPref& codec_pref, int ptime_ms) { |
459 int selected_packet_size_ms = codec_pref.packet_sizes_ms[0]; | 459 int selected_packet_size_ms = codec_pref.packet_sizes_ms[0]; |
460 for (int packet_size_ms : codec_pref.packet_sizes_ms) { | 460 for (int packet_size_ms : codec_pref.packet_sizes_ms) { |
461 if (packet_size_ms && packet_size_ms <= ptime_ms) { | 461 if (packet_size_ms && packet_size_ms <= ptime_ms) { |
462 selected_packet_size_ms = packet_size_ms; | 462 selected_packet_size_ms = packet_size_ms; |
463 } | 463 } |
464 } | 464 } |
465 return selected_packet_size_ms; | 465 return selected_packet_size_ms; |
466 } | 466 } |
467 | 467 |
468 // Changes RTP timestamp rate of G722. This is due to the "bug" in the RFC | 468 // Changes RTP timestamp rate of G722. This is due to the "bug" in the RFC |
469 // which says that G722 should be advertised as 8 kHz although it is a 16 kHz | 469 // which says that G722 should be advertised as 8 kHz although it is a 16 kHz |
470 // codec. | 470 // codec. |
471 static void MaybeFixupG722(webrtc::CodecInst* voe_codec, int new_plfreq) { | 471 static void MaybeFixupG722(webrtc::CodecInst* voe_codec, int new_plfreq) { |
472 if (IsCodec(*voe_codec, kG722CodecName)) { | 472 if (IsCodec(*voe_codec, kG722CodecName)) { |
473 // If the ASSERT triggers, the codec definition in WebRTC VoiceEngine | 473 // If the ASSERT triggers, the codec definition in WebRTC VoiceEngine |
474 // has changed, and this special case is no longer needed. | 474 // has changed, and this special case is no longer needed. |
475 RTC_DCHECK(voe_codec->plfreq != new_plfreq); | 475 RTC_DCHECK(voe_codec->plfreq != new_plfreq); |
476 voe_codec->plfreq = new_plfreq; | 476 voe_codec->plfreq = new_plfreq; |
477 } | 477 } |
478 } | 478 } |
479 }; | 479 }; |
480 | 480 |
481 const WebRtcVoiceCodecs::CodecPref WebRtcVoiceCodecs::kCodecPrefs[11] = { | 481 const WebRtcVoiceCodecs::CodecPref WebRtcVoiceCodecs::kCodecPrefs[14] = { |
482 {kOpusCodecName, 48000, 2, 111, true, {10, 20, 40, 60}, kOpusMaxBitrateBps}, | 482 {kOpusCodecName, 48000, 2, 111, true, {10, 20, 40, 60}, kOpusMaxBitrateBps}, |
483 {kIsacCodecName, 16000, 1, 103, true, {30, 60}, kIsacMaxBitrateBps}, | 483 {kIsacCodecName, 16000, 1, 103, true, {30, 60}, kIsacMaxBitrateBps}, |
484 {kIsacCodecName, 32000, 1, 104, true, {30}, kIsacMaxBitrateBps}, | 484 {kIsacCodecName, 32000, 1, 104, true, {30}, kIsacMaxBitrateBps}, |
485 // G722 should be advertised as 8000 Hz because of the RFC "bug". | 485 // G722 should be advertised as 8000 Hz because of the RFC "bug". |
486 {kG722CodecName, 8000, 1, 9, false, {10, 20, 30, 40, 50, 60}}, | 486 {kG722CodecName, 8000, 1, 9, false, {10, 20, 30, 40, 50, 60}}, |
487 {kIlbcCodecName, 8000, 1, 102, false, {20, 30, 40, 60}}, | 487 {kIlbcCodecName, 8000, 1, 102, false, {20, 30, 40, 60}}, |
488 {kPcmuCodecName, 8000, 1, 0, false, {10, 20, 30, 40, 50, 60}}, | 488 {kPcmuCodecName, 8000, 1, 0, false, {10, 20, 30, 40, 50, 60}}, |
489 {kPcmaCodecName, 8000, 1, 8, false, {10, 20, 30, 40, 50, 60}}, | 489 {kPcmaCodecName, 8000, 1, 8, false, {10, 20, 30, 40, 50, 60}}, |
490 {kCnCodecName, 32000, 1, 106, false, {}}, | 490 {kCnCodecName, 32000, 1, 106, false, {}}, |
491 {kCnCodecName, 16000, 1, 105, false, {}}, | 491 {kCnCodecName, 16000, 1, 105, false, {}}, |
492 {kCnCodecName, 8000, 1, 13, false, {}}, | 492 {kCnCodecName, 8000, 1, 13, false, {}}, |
493 {kDtmfCodecName, 8000, 1, 126, false, {}}}; | 493 {kDtmfCodecName, 48000, 1, 110, false, {}}, |
| 494 {kDtmfCodecName, 32000, 1, 112, false, {}}, |
| 495 {kDtmfCodecName, 16000, 1, 113, false, {}}, |
| 496 {kDtmfCodecName, 8000, 1, 126, false, {}} |
| 497 }; |
494 | 498 |
495 rtc::Optional<int> ComputeSendBitrate(int max_send_bitrate_bps, | 499 rtc::Optional<int> ComputeSendBitrate(int max_send_bitrate_bps, |
496 int rtp_max_bitrate_bps, | 500 int rtp_max_bitrate_bps, |
497 const webrtc::CodecInst& codec_inst) { | 501 const webrtc::CodecInst& codec_inst) { |
498 const int bps = MinPositive(max_send_bitrate_bps, rtp_max_bitrate_bps); | 502 const int bps = MinPositive(max_send_bitrate_bps, rtp_max_bitrate_bps); |
499 const int codec_rate = codec_inst.rate; | 503 const int codec_rate = codec_inst.rate; |
500 | 504 |
501 if (bps <= 0) { | 505 if (bps <= 0) { |
502 return rtc::Optional<int>(codec_rate); | 506 return rtc::Optional<int>(codec_rate); |
503 } | 507 } |
(...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1117 RTC_DCHECK(apm_); | 1121 RTC_DCHECK(apm_); |
1118 return apm_; | 1122 return apm_; |
1119 } | 1123 } |
1120 | 1124 |
1121 AudioCodecs WebRtcVoiceEngine::CollectRecvCodecs() const { | 1125 AudioCodecs WebRtcVoiceEngine::CollectRecvCodecs() const { |
1122 PayloadTypeMapper mapper; | 1126 PayloadTypeMapper mapper; |
1123 AudioCodecs out; | 1127 AudioCodecs out; |
1124 const std::vector<webrtc::AudioCodecSpec>& specs = | 1128 const std::vector<webrtc::AudioCodecSpec>& specs = |
1125 decoder_factory_->GetSupportedDecoders(); | 1129 decoder_factory_->GetSupportedDecoders(); |
1126 | 1130 |
1127 // Only generate CN payload types for these clockrates | 1131 // Only generate CN payload types for these clockrates: |
1128 std::map<int, bool, std::greater<int>> generate_cn = {{ 8000, false }, | 1132 std::map<int, bool, std::greater<int>> generate_cn = {{ 8000, false }, |
1129 { 16000, false }, | 1133 { 16000, false }, |
1130 { 32000, false }}; | 1134 { 32000, false }}; |
| 1135 // Only generate telephone-event payload types for these clockrates: |
| 1136 std::map<int, bool, std::greater<int>> generate_dtmf = {{ 8000, false }, |
| 1137 { 16000, false }, |
| 1138 { 32000, false }, |
| 1139 { 48000, false }}; |
1131 | 1140 |
1132 auto map_format = [&mapper, &out] (const webrtc::SdpAudioFormat& format) { | 1141 auto map_format = [&mapper, &out] (const webrtc::SdpAudioFormat& format) { |
1133 rtc::Optional<AudioCodec> opt_codec = mapper.ToAudioCodec(format); | 1142 rtc::Optional<AudioCodec> opt_codec = mapper.ToAudioCodec(format); |
1134 if (!opt_codec) { | 1143 if (!opt_codec) { |
1135 LOG(LS_ERROR) << "Unable to assign payload type to format: " << format; | 1144 LOG(LS_ERROR) << "Unable to assign payload type to format: " << format; |
1136 return false; | 1145 return false; |
1137 } | 1146 } |
1138 | 1147 |
1139 auto& codec = *opt_codec; | 1148 auto& codec = *opt_codec; |
1140 if (IsCodec(codec, kOpusCodecName)) { | 1149 if (IsCodec(codec, kOpusCodecName)) { |
1141 // TODO(ossu): Set this specifically for Opus for now, until we have a | 1150 // TODO(ossu): Set this specifically for Opus for now, until we have a |
1142 // better way of dealing with rtcp-fb parameters. | 1151 // better way of dealing with rtcp-fb parameters. |
1143 codec.AddFeedbackParam( | 1152 codec.AddFeedbackParam( |
1144 FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty)); | 1153 FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty)); |
1145 } | 1154 } |
1146 out.push_back(codec); | 1155 out.push_back(codec); |
1147 return true; | 1156 return true; |
1148 }; | 1157 }; |
1149 | 1158 |
1150 for (const auto& spec : specs) { | 1159 for (const auto& spec : specs) { |
1151 if (map_format(spec.format) && spec.allow_comfort_noise) { | 1160 if (map_format(spec.format)) { |
1152 // Generate a CN entry if the decoder allows it and we support the | 1161 if (spec.allow_comfort_noise) { |
1153 // clockrate. | 1162 // Generate a CN entry if the decoder allows it and we support the |
1154 auto cn = generate_cn.find(spec.format.clockrate_hz); | 1163 // clockrate. |
1155 if (cn != generate_cn.end()) { | 1164 auto cn = generate_cn.find(spec.format.clockrate_hz); |
1156 cn->second = true; | 1165 if (cn != generate_cn.end()) { |
| 1166 cn->second = true; |
| 1167 } |
| 1168 } |
| 1169 |
| 1170 // Generate a telephone-event entry if we support the clockrate. |
| 1171 auto dtmf = generate_dtmf.find(spec.format.clockrate_hz); |
| 1172 if (dtmf != generate_dtmf.end()) { |
| 1173 dtmf->second = true; |
1157 } | 1174 } |
1158 } | 1175 } |
1159 } | 1176 } |
1160 | 1177 |
1161 // Add CN codecs after "proper" audio codecs | 1178 // Add CN codecs after "proper" audio codecs. |
1162 for (const auto& cn : generate_cn) { | 1179 for (const auto& cn : generate_cn) { |
1163 if (cn.second) { | 1180 if (cn.second) { |
1164 map_format({kCnCodecName, cn.first, 1}); | 1181 map_format({kCnCodecName, cn.first, 1}); |
1165 } | 1182 } |
1166 } | 1183 } |
1167 | 1184 |
1168 // Add telephone-event codec last | 1185 // Add telephone-event codecs last. |
1169 map_format({kDtmfCodecName, 8000, 1}); | 1186 for (const auto& dtmf : generate_dtmf) { |
| 1187 if (dtmf.second) { |
| 1188 map_format({kDtmfCodecName, dtmf.first, 1}); |
| 1189 } |
| 1190 } |
1170 | 1191 |
1171 return out; | 1192 return out; |
1172 } | 1193 } |
1173 | 1194 |
1174 class WebRtcVoiceMediaChannel::WebRtcAudioSendStream | 1195 class WebRtcVoiceMediaChannel::WebRtcAudioSendStream |
1175 : public AudioSource::Sink { | 1196 : public AudioSource::Sink { |
1176 public: | 1197 public: |
1177 WebRtcAudioSendStream( | 1198 WebRtcAudioSendStream( |
1178 int ch, | 1199 int ch, |
1179 webrtc::AudioTransport* voe_audio_transport, | 1200 webrtc::AudioTransport* voe_audio_transport, |
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1787 LOG(LS_ERROR) << "Codec payload types overlap."; | 1808 LOG(LS_ERROR) << "Codec payload types overlap."; |
1788 return false; | 1809 return false; |
1789 } | 1810 } |
1790 | 1811 |
1791 std::vector<AudioCodec> new_codecs; | 1812 std::vector<AudioCodec> new_codecs; |
1792 // Find all new codecs. We allow adding new codecs but don't allow changing | 1813 // Find all new codecs. We allow adding new codecs but don't allow changing |
1793 // the payload type of codecs that is already configured since we might | 1814 // the payload type of codecs that is already configured since we might |
1794 // already be receiving packets with that payload type. | 1815 // already be receiving packets with that payload type. |
1795 for (const AudioCodec& codec : codecs) { | 1816 for (const AudioCodec& codec : codecs) { |
1796 AudioCodec old_codec; | 1817 AudioCodec old_codec; |
| 1818 // TODO(solenberg): This isn't strictly correct. It should be possible to |
| 1819 // add an additional payload type for a codec. That would result in a new |
| 1820 // decoder object being allocated. What shouldn't work is to remove a PT |
| 1821 // mapping that was previously configured. |
1797 if (FindCodec(recv_codecs_, codec, &old_codec)) { | 1822 if (FindCodec(recv_codecs_, codec, &old_codec)) { |
1798 if (old_codec.id != codec.id) { | 1823 if (old_codec.id != codec.id) { |
1799 LOG(LS_ERROR) << codec.name << " payload type changed."; | 1824 LOG(LS_ERROR) << codec.name << " payload type changed."; |
1800 return false; | 1825 return false; |
1801 } | 1826 } |
1802 } else { | 1827 } else { |
1803 new_codecs.push_back(codec); | 1828 new_codecs.push_back(codec); |
1804 } | 1829 } |
1805 } | 1830 } |
1806 if (new_codecs.empty()) { | 1831 if (new_codecs.empty()) { |
(...skipping 771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2578 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 2603 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
2579 const auto it = send_streams_.find(ssrc); | 2604 const auto it = send_streams_.find(ssrc); |
2580 if (it != send_streams_.end()) { | 2605 if (it != send_streams_.end()) { |
2581 return it->second->channel(); | 2606 return it->second->channel(); |
2582 } | 2607 } |
2583 return -1; | 2608 return -1; |
2584 } | 2609 } |
2585 } // namespace cricket | 2610 } // namespace cricket |
2586 | 2611 |
2587 #endif // HAVE_WEBRTC_VOICE | 2612 #endif // HAVE_WEBRTC_VOICE |
OLD | NEW |