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

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

Issue 1491743004: Refactor WVoE DTMF handling #2 (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@wvoe_dtmf
Patch Set: rebase Created 5 years 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
« no previous file with comments | « talk/media/webrtc/webrtcvoiceengine.h ('k') | talk/media/webrtc/webrtcvoiceengine_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 // NOTE(ajm): Don't use hardcoded paths on platforms not explicitly specified 127 // NOTE(ajm): Don't use hardcoded paths on platforms not explicitly specified
128 // below. 128 // below.
129 #if defined(CHROMEOS) 129 #if defined(CHROMEOS)
130 const char kAecDumpByAudioOptionFilename[] = "/tmp/audio.aecdump"; 130 const char kAecDumpByAudioOptionFilename[] = "/tmp/audio.aecdump";
131 #elif defined(ANDROID) 131 #elif defined(ANDROID)
132 const char kAecDumpByAudioOptionFilename[] = "/sdcard/audio.aecdump"; 132 const char kAecDumpByAudioOptionFilename[] = "/sdcard/audio.aecdump";
133 #else 133 #else
134 const char kAecDumpByAudioOptionFilename[] = "audio.aecdump"; 134 const char kAecDumpByAudioOptionFilename[] = "audio.aecdump";
135 #endif 135 #endif
136 136
137 // Constants from voice_engine_defines.h.
138 const int kMinTelephoneEventCode = 0; // RFC4733 (Section 2.3.1)
139 const int kMaxTelephoneEventCode = 255;
140 const int kMinTelephoneEventDuration = 100;
141 const int kMaxTelephoneEventDuration = 60000; // Actual limit is 2^16
142
137 bool ValidateStreamParams(const StreamParams& sp) { 143 bool ValidateStreamParams(const StreamParams& sp) {
138 if (sp.ssrcs.empty()) { 144 if (sp.ssrcs.empty()) {
139 LOG(LS_ERROR) << "No SSRCs in stream parameters: " << sp.ToString(); 145 LOG(LS_ERROR) << "No SSRCs in stream parameters: " << sp.ToString();
140 return false; 146 return false;
141 } 147 }
142 if (sp.ssrcs.size() > 1) { 148 if (sp.ssrcs.size() > 1) {
143 LOG(LS_ERROR) << "Multiple SSRCs in stream parameters: " << sp.ToString(); 149 LOG(LS_ERROR) << "Multiple SSRCs in stream parameters: " << sp.ToString();
144 return false; 150 return false;
145 } 151 }
146 return true; 152 return true;
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 if (!SetOptions(GetDefaultEngineOptions())) { 581 if (!SetOptions(GetDefaultEngineOptions())) {
576 return false; 582 return false;
577 } 583 }
578 584
579 // Print our codec list again for the call diagnostic log 585 // Print our codec list again for the call diagnostic log
580 LOG(LS_INFO) << "WebRtc VoiceEngine codecs:"; 586 LOG(LS_INFO) << "WebRtc VoiceEngine codecs:";
581 for (const AudioCodec& codec : codecs_) { 587 for (const AudioCodec& codec : codecs_) {
582 LOG(LS_INFO) << ToString(codec); 588 LOG(LS_INFO) << ToString(codec);
583 } 589 }
584 590
585 // Disable the DTMF playout when a tone is sent.
586 // PlayDtmfTone will be used if local playout is needed.
587 if (voe_wrapper_->dtmf()->SetDtmfFeedbackStatus(false) == -1) {
588 LOG_RTCERR1(SetDtmfFeedbackStatus, false);
589 }
590
591 initialized_ = true; 591 initialized_ = true;
592 return true; 592 return true;
593 } 593 }
594 594
595 void WebRtcVoiceEngine::Terminate() { 595 void WebRtcVoiceEngine::Terminate() {
596 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 596 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
597 LOG(LS_INFO) << "WebRtcVoiceEngine::Terminate"; 597 LOG(LS_INFO) << "WebRtcVoiceEngine::Terminate";
598 initialized_ = false; 598 initialized_ = false;
599 599
600 StopAecDump(); 600 StopAecDump();
(...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after
1251 if (stream_) { 1251 if (stream_) {
1252 call_->DestroyAudioSendStream(stream_); 1252 call_->DestroyAudioSendStream(stream_);
1253 stream_ = nullptr; 1253 stream_ = nullptr;
1254 } 1254 }
1255 config_.rtp.extensions = extensions; 1255 config_.rtp.extensions = extensions;
1256 RTC_DCHECK(!stream_); 1256 RTC_DCHECK(!stream_);
1257 stream_ = call_->CreateAudioSendStream(config_); 1257 stream_ = call_->CreateAudioSendStream(config_);
1258 RTC_CHECK(stream_); 1258 RTC_CHECK(stream_);
1259 } 1259 }
1260 1260
1261 bool SendTelephoneEvent(int payload_type, uint8_t event,
1262 uint32_t duration_ms) {
1263 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1264 RTC_DCHECK(stream_);
1265 return stream_->SendTelephoneEvent(payload_type, event, duration_ms);
1266 }
1267
1261 webrtc::AudioSendStream::Stats GetStats() const { 1268 webrtc::AudioSendStream::Stats GetStats() const {
1262 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1269 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1263 RTC_DCHECK(stream_); 1270 RTC_DCHECK(stream_);
1264 return stream_->GetStats(); 1271 return stream_->GetStats();
1265 } 1272 }
1266 1273
1267 // Starts the rendering by setting a sink to the renderer to get data 1274 // Starts the rendering by setting a sink to the renderer to get data
1268 // callback. 1275 // callback.
1269 // This method is called on the libjingle worker thread. 1276 // This method is called on the libjingle worker thread.
1270 // TODO(xians): Make sure Start() is called only once. 1277 // TODO(xians): Make sure Start() is called only once.
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
1605 1612
1606 bool WebRtcVoiceMediaChannel::SetSendCodecs( 1613 bool WebRtcVoiceMediaChannel::SetSendCodecs(
1607 int channel, const std::vector<AudioCodec>& codecs) { 1614 int channel, const std::vector<AudioCodec>& codecs) {
1608 // Disable VAD, FEC, and RED unless we know the other side wants them. 1615 // Disable VAD, FEC, and RED unless we know the other side wants them.
1609 engine()->voe()->codec()->SetVADStatus(channel, false); 1616 engine()->voe()->codec()->SetVADStatus(channel, false);
1610 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); 1617 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0);
1611 engine()->voe()->rtp()->SetREDStatus(channel, false); 1618 engine()->voe()->rtp()->SetREDStatus(channel, false);
1612 engine()->voe()->codec()->SetFECStatus(channel, false); 1619 engine()->voe()->codec()->SetFECStatus(channel, false);
1613 1620
1614 // Scan through the list to figure out the codec to use for sending, along 1621 // Scan through the list to figure out the codec to use for sending, along
1615 // with the proper configuration for VAD and DTMF. 1622 // with the proper configuration for VAD.
1616 bool found_send_codec = false; 1623 bool found_send_codec = false;
1617 webrtc::CodecInst send_codec; 1624 webrtc::CodecInst send_codec;
1618 memset(&send_codec, 0, sizeof(send_codec)); 1625 memset(&send_codec, 0, sizeof(send_codec));
1619 1626
1620 bool nack_enabled = nack_enabled_; 1627 bool nack_enabled = nack_enabled_;
1621 bool enable_codec_fec = false; 1628 bool enable_codec_fec = false;
1622 bool enable_opus_dtx = false; 1629 bool enable_opus_dtx = false;
1623 int opus_max_playback_rate = 0; 1630 int opus_max_playback_rate = 0;
1624 1631
1625 // Set send codec (the first non-telephone-event/CN codec) 1632 // Set send codec (the first non-telephone-event/CN codec)
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
1734 } 1741 }
1735 } 1742 }
1736 1743
1737 // Always update the |send_codec_| to the currently set send codec. 1744 // Always update the |send_codec_| to the currently set send codec.
1738 send_codec_.reset(new webrtc::CodecInst(send_codec)); 1745 send_codec_.reset(new webrtc::CodecInst(send_codec));
1739 1746
1740 if (send_bitrate_setting_) { 1747 if (send_bitrate_setting_) {
1741 SetSendBitrateInternal(send_bitrate_bps_); 1748 SetSendBitrateInternal(send_bitrate_bps_);
1742 } 1749 }
1743 1750
1744 // Loop through the codecs list again to config the telephone-event/CN codec. 1751 // Loop through the codecs list again to config the CN codec.
1745 for (const AudioCodec& codec : codecs) { 1752 for (const AudioCodec& codec : codecs) {
1746 // Ignore codecs we don't know about. The negotiation step should prevent 1753 // Ignore codecs we don't know about. The negotiation step should prevent
1747 // this, but double-check to be sure. 1754 // this, but double-check to be sure.
1748 webrtc::CodecInst voe_codec; 1755 webrtc::CodecInst voe_codec;
1749 if (!WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) { 1756 if (!WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) {
1750 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); 1757 LOG(LS_WARNING) << "Unknown codec " << ToString(codec);
1751 continue; 1758 continue;
1752 } 1759 }
1753 1760
1754 // Find the DTMF telephone event "codec" and tell VoiceEngine channels 1761 if (IsCodec(codec, kCnCodecName)) {
1755 // about it.
1756 if (IsCodec(codec, kDtmfCodecName)) {
1757 if (engine()->voe()->dtmf()->SetSendTelephoneEventPayloadType(
1758 channel, codec.id) == -1) {
1759 LOG_RTCERR2(SetSendTelephoneEventPayloadType, channel, codec.id);
1760 return false;
1761 }
1762 } else if (IsCodec(codec, kCnCodecName)) {
1763 // Turn voice activity detection/comfort noise on if supported. 1762 // Turn voice activity detection/comfort noise on if supported.
1764 // Set the wideband CN payload type appropriately. 1763 // Set the wideband CN payload type appropriately.
1765 // (narrowband always uses the static payload type 13). 1764 // (narrowband always uses the static payload type 13).
1766 webrtc::PayloadFrequencies cn_freq; 1765 webrtc::PayloadFrequencies cn_freq;
1767 switch (codec.clockrate) { 1766 switch (codec.clockrate) {
1768 case 8000: 1767 case 8000:
1769 cn_freq = webrtc::kFreq8000Hz; 1768 cn_freq = webrtc::kFreq8000Hz;
1770 break; 1769 break;
1771 case 16000: 1770 case 16000:
1772 cn_freq = webrtc::kFreq16000Hz; 1771 cn_freq = webrtc::kFreq16000Hz;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1807 } 1806 }
1808 } 1807 }
1809 } 1808 }
1810 } 1809 }
1811 return true; 1810 return true;
1812 } 1811 }
1813 1812
1814 bool WebRtcVoiceMediaChannel::SetSendCodecs( 1813 bool WebRtcVoiceMediaChannel::SetSendCodecs(
1815 const std::vector<AudioCodec>& codecs) { 1814 const std::vector<AudioCodec>& codecs) {
1816 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1815 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1816 // TODO(solenberg): Validate input - that payload types don't overlap, are
1817 // within range, filter out codecs we don't support,
1818 // redundant codecs etc.
1817 1819
1818 dtmf_allowed_ = false; 1820 // Find the DTMF telephone event "codec" payload type.
1821 dtmf_payload_type_ = rtc::Optional<int>();
1819 for (const AudioCodec& codec : codecs) { 1822 for (const AudioCodec& codec : codecs) {
1820 // Find the DTMF telephone event "codec".
1821 if (IsCodec(codec, kDtmfCodecName)) { 1823 if (IsCodec(codec, kDtmfCodecName)) {
1822 dtmf_allowed_ = true; 1824 dtmf_payload_type_ = rtc::Optional<int>(codec.id);
1825 break;
1823 } 1826 }
1824 } 1827 }
1825 1828
1826 // Cache the codecs in order to configure the channel created later. 1829 // Cache the codecs in order to configure the channel created later.
1827 send_codecs_ = codecs; 1830 send_codecs_ = codecs;
1828 for (const auto& ch : send_streams_) { 1831 for (const auto& ch : send_streams_) {
1829 if (!SetSendCodecs(ch.second->channel(), codecs)) { 1832 if (!SetSendCodecs(ch.second->channel(), codecs)) {
1830 return false; 1833 return false;
1831 } 1834 }
1832 } 1835 }
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after
2275 volume)) { 2278 volume)) {
2276 LOG_RTCERR2(SetChannelOutputVolumeScaling, ch_id, volume); 2279 LOG_RTCERR2(SetChannelOutputVolumeScaling, ch_id, volume);
2277 return false; 2280 return false;
2278 } 2281 }
2279 LOG(LS_INFO) << "SetOutputVolume to " << volume 2282 LOG(LS_INFO) << "SetOutputVolume to " << volume
2280 << " for channel " << ch_id << " and ssrc " << ssrc; 2283 << " for channel " << ch_id << " and ssrc " << ssrc;
2281 return true; 2284 return true;
2282 } 2285 }
2283 2286
2284 bool WebRtcVoiceMediaChannel::CanInsertDtmf() { 2287 bool WebRtcVoiceMediaChannel::CanInsertDtmf() {
2285 return dtmf_allowed_; 2288 return dtmf_payload_type_ ? true : false;
2286 } 2289 }
2287 2290
2288 bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc, int event, 2291 bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc, int event,
2289 int duration) { 2292 int duration) {
2290 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 2293 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2291 if (!dtmf_allowed_) { 2294 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::InsertDtmf";
2295 if (!dtmf_payload_type_) {
2292 return false; 2296 return false;
2293 } 2297 }
2294 2298
2295 // Send the event. 2299 // Figure out which WebRtcAudioSendStream to send the event on.
2296 int channel = -1; 2300 auto it = ssrc != 0 ? send_streams_.find(ssrc) : send_streams_.begin();
2297 if (ssrc == 0) { 2301 if (it == send_streams_.end()) {
2298 if (send_streams_.size() > 0) { 2302 LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
2299 channel = send_streams_.begin()->second->channel();
2300 }
2301 } else {
2302 channel = GetSendChannelId(ssrc);
2303 }
2304 if (channel == -1) {
2305 LOG(LS_WARNING) << "InsertDtmf - The specified ssrc "
2306 << ssrc << " is not in use.";
2307 return false; 2303 return false;
2308 } 2304 }
2309 // Send DTMF using out-of-band DTMF. ("true", as 3rd arg) 2305 if (event < kMinTelephoneEventCode ||
2310 if (engine()->voe()->dtmf()->SendTelephoneEvent( 2306 event > kMaxTelephoneEventCode) {
2311 channel, event, true, duration) == -1) { 2307 LOG(LS_WARNING) << "DTMF event code " << event << " out of range.";
2312 LOG_RTCERR4(SendTelephoneEvent, channel, event, true, duration);
2313 return false; 2308 return false;
2314 } 2309 }
2315 2310 if (duration < kMinTelephoneEventDuration ||
2316 return true; 2311 duration > kMaxTelephoneEventDuration) {
2312 LOG(LS_WARNING) << "DTMF event duration " << duration << " out of range.";
2313 return false;
2314 }
2315 return it->second->SendTelephoneEvent(*dtmf_payload_type_, event, duration);
2317 } 2316 }
2318 2317
2319 void WebRtcVoiceMediaChannel::OnPacketReceived( 2318 void WebRtcVoiceMediaChannel::OnPacketReceived(
2320 rtc::Buffer* packet, const rtc::PacketTime& packet_time) { 2319 rtc::Buffer* packet, const rtc::PacketTime& packet_time) {
2321 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 2320 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2322 2321
2323 uint32_t ssrc = 0; 2322 uint32_t ssrc = 0;
2324 if (!GetRtpSsrc(packet->data(), packet->size(), &ssrc)) { 2323 if (!GetRtpSsrc(packet->data(), packet->size(), &ssrc)) {
2325 return; 2324 return;
2326 } 2325 }
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after
2638 } 2637 }
2639 } else { 2638 } else {
2640 LOG(LS_INFO) << "Stopping playout for channel #" << channel; 2639 LOG(LS_INFO) << "Stopping playout for channel #" << channel;
2641 engine()->voe()->base()->StopPlayout(channel); 2640 engine()->voe()->base()->StopPlayout(channel);
2642 } 2641 }
2643 return true; 2642 return true;
2644 } 2643 }
2645 } // namespace cricket 2644 } // namespace cricket
2646 2645
2647 #endif // HAVE_WEBRTC_VOICE 2646 #endif // HAVE_WEBRTC_VOICE
OLDNEW
« no previous file with comments | « talk/media/webrtc/webrtcvoiceengine.h ('k') | talk/media/webrtc/webrtcvoiceengine_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698