| 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 |