Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: webrtc/media/engine/webrtcvoiceengine.cc

Issue 2337473002: Multi frequency DTMF support - receiver side (Closed)
Patch Set: rebase Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698