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

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: remove commented out lines 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
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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 // NOTE(ajm): Don't use hardcoded paths on platforms not explicitly specified 126 // NOTE(ajm): Don't use hardcoded paths on platforms not explicitly specified
127 // below. 127 // below.
128 #if defined(CHROMEOS) 128 #if defined(CHROMEOS)
129 const char kAecDumpByAudioOptionFilename[] = "/tmp/audio.aecdump"; 129 const char kAecDumpByAudioOptionFilename[] = "/tmp/audio.aecdump";
130 #elif defined(ANDROID) 130 #elif defined(ANDROID)
131 const char kAecDumpByAudioOptionFilename[] = "/sdcard/audio.aecdump"; 131 const char kAecDumpByAudioOptionFilename[] = "/sdcard/audio.aecdump";
132 #else 132 #else
133 const char kAecDumpByAudioOptionFilename[] = "audio.aecdump"; 133 const char kAecDumpByAudioOptionFilename[] = "audio.aecdump";
134 #endif 134 #endif
135 135
136 // Constants from voice_engine_defines.h.
137 const int kMinTelephoneEventCode = 0; // RFC4733 (Section 2.3.1)
138 const int kMaxTelephoneEventCode = 255;
139 const int kMinTelephoneEventDuration = 100;
140 const int kMaxTelephoneEventDuration = 60000; // Actual limit is 2^16
141
136 bool ValidateStreamParams(const StreamParams& sp) { 142 bool ValidateStreamParams(const StreamParams& sp) {
137 if (sp.ssrcs.empty()) { 143 if (sp.ssrcs.empty()) {
138 LOG(LS_ERROR) << "No SSRCs in stream parameters: " << sp.ToString(); 144 LOG(LS_ERROR) << "No SSRCs in stream parameters: " << sp.ToString();
139 return false; 145 return false;
140 } 146 }
141 if (sp.ssrcs.size() > 1) { 147 if (sp.ssrcs.size() > 1) {
142 LOG(LS_ERROR) << "Multiple SSRCs in stream parameters: " << sp.ToString(); 148 LOG(LS_ERROR) << "Multiple SSRCs in stream parameters: " << sp.ToString();
143 return false; 149 return false;
144 } 150 }
145 return true; 151 return true;
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 if (!SetOptions(GetDefaultEngineOptions())) { 594 if (!SetOptions(GetDefaultEngineOptions())) {
589 return false; 595 return false;
590 } 596 }
591 597
592 // Print our codec list again for the call diagnostic log 598 // Print our codec list again for the call diagnostic log
593 LOG(LS_INFO) << "WebRtc VoiceEngine codecs:"; 599 LOG(LS_INFO) << "WebRtc VoiceEngine codecs:";
594 for (const AudioCodec& codec : codecs_) { 600 for (const AudioCodec& codec : codecs_) {
595 LOG(LS_INFO) << ToString(codec); 601 LOG(LS_INFO) << ToString(codec);
596 } 602 }
597 603
598 // Disable the DTMF playout when a tone is sent.
599 // PlayDtmfTone will be used if local playout is needed.
600 if (voe_wrapper_->dtmf()->SetDtmfFeedbackStatus(false) == -1) {
601 LOG_RTCERR1(SetDtmfFeedbackStatus, false);
602 }
603
604 initialized_ = true; 604 initialized_ = true;
605 return true; 605 return true;
606 } 606 }
607 607
608 void WebRtcVoiceEngine::Terminate() { 608 void WebRtcVoiceEngine::Terminate() {
609 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 609 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
610 LOG(LS_INFO) << "WebRtcVoiceEngine::Terminate"; 610 LOG(LS_INFO) << "WebRtcVoiceEngine::Terminate";
611 initialized_ = false; 611 initialized_ = false;
612 612
613 StopAecDump(); 613 StopAecDump();
(...skipping 709 matching lines...) Expand 10 before | Expand all | Expand 10 after
1323 1323
1324 // Callback from the |renderer_| when it is going away. In case Start() has 1324 // Callback from the |renderer_| when it is going away. In case Start() has
1325 // never been called, this callback won't be triggered. 1325 // never been called, this callback won't be triggered.
1326 void OnClose() override { 1326 void OnClose() override {
1327 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1327 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1328 // Set |renderer_| to nullptr to make sure no more callback will get into 1328 // Set |renderer_| to nullptr to make sure no more callback will get into
1329 // the renderer. 1329 // the renderer.
1330 renderer_ = nullptr; 1330 renderer_ = nullptr;
1331 } 1331 }
1332 1332
1333 // Accessor to the Call stream.
1334 webrtc::AudioSendStream* stream() {
1335 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1336 RTC_DCHECK(stream_);
1337 return stream_;
pthatcher1 2015/12/02 18:45:37 Rather than expose the stream underneath, it seems
the sun 2015/12/03 09:57:47 Done.
1338 }
1339
1333 // Accessor to the VoE channel ID. 1340 // Accessor to the VoE channel ID.
1334 int channel() const { 1341 int channel() const {
1335 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1342 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1336 return config_.voe_channel_id; 1343 return config_.voe_channel_id;
1337 } 1344 }
1338 1345
1339 private: 1346 private:
1340 rtc::ThreadChecker worker_thread_checker_; 1347 rtc::ThreadChecker worker_thread_checker_;
1341 rtc::ThreadChecker audio_capture_thread_checker_; 1348 rtc::ThreadChecker audio_capture_thread_checker_;
1342 webrtc::AudioTransport* const voe_audio_transport_ = nullptr; 1349 webrtc::AudioTransport* const voe_audio_transport_ = nullptr;
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
1606 1613
1607 bool WebRtcVoiceMediaChannel::SetSendCodecs( 1614 bool WebRtcVoiceMediaChannel::SetSendCodecs(
1608 int channel, const std::vector<AudioCodec>& codecs) { 1615 int channel, const std::vector<AudioCodec>& codecs) {
1609 // Disable VAD, FEC, and RED unless we know the other side wants them. 1616 // Disable VAD, FEC, and RED unless we know the other side wants them.
1610 engine()->voe()->codec()->SetVADStatus(channel, false); 1617 engine()->voe()->codec()->SetVADStatus(channel, false);
1611 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); 1618 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0);
1612 engine()->voe()->rtp()->SetREDStatus(channel, false); 1619 engine()->voe()->rtp()->SetREDStatus(channel, false);
1613 engine()->voe()->codec()->SetFECStatus(channel, false); 1620 engine()->voe()->codec()->SetFECStatus(channel, false);
1614 1621
1615 // Scan through the list to figure out the codec to use for sending, along 1622 // Scan through the list to figure out the codec to use for sending, along
1616 // with the proper configuration for VAD and DTMF. 1623 // with the proper configuration for VAD.
1617 bool found_send_codec = false; 1624 bool found_send_codec = false;
1618 webrtc::CodecInst send_codec; 1625 webrtc::CodecInst send_codec;
1619 memset(&send_codec, 0, sizeof(send_codec)); 1626 memset(&send_codec, 0, sizeof(send_codec));
1620 1627
1621 bool nack_enabled = nack_enabled_; 1628 bool nack_enabled = nack_enabled_;
1622 bool enable_codec_fec = false; 1629 bool enable_codec_fec = false;
1623 bool enable_opus_dtx = false; 1630 bool enable_opus_dtx = false;
1624 int opus_max_playback_rate = 0; 1631 int opus_max_playback_rate = 0;
1625 1632
1626 // Set send codec (the first non-telephone-event/CN codec) 1633 // Set send codec (the first non-telephone-event/CN codec)
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
1735 } 1742 }
1736 } 1743 }
1737 1744
1738 // Always update the |send_codec_| to the currently set send codec. 1745 // Always update the |send_codec_| to the currently set send codec.
1739 send_codec_.reset(new webrtc::CodecInst(send_codec)); 1746 send_codec_.reset(new webrtc::CodecInst(send_codec));
1740 1747
1741 if (send_bitrate_setting_) { 1748 if (send_bitrate_setting_) {
1742 SetSendBitrateInternal(send_bitrate_bps_); 1749 SetSendBitrateInternal(send_bitrate_bps_);
1743 } 1750 }
1744 1751
1745 // Loop through the codecs list again to config the telephone-event/CN codec. 1752 // Loop through the codecs list again to config the CN codec.
1746 for (const AudioCodec& codec : codecs) { 1753 for (const AudioCodec& codec : codecs) {
1747 // Ignore codecs we don't know about. The negotiation step should prevent 1754 // Ignore codecs we don't know about. The negotiation step should prevent
1748 // this, but double-check to be sure. 1755 // this, but double-check to be sure.
1749 webrtc::CodecInst voe_codec; 1756 webrtc::CodecInst voe_codec;
1750 if (!WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) { 1757 if (!WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) {
1751 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); 1758 LOG(LS_WARNING) << "Unknown codec " << ToString(codec);
1752 continue; 1759 continue;
1753 } 1760 }
1754 1761
1755 // Find the DTMF telephone event "codec" and tell VoiceEngine channels 1762 if (IsCodec(codec, kCnCodecName)) {
1756 // about it.
1757 if (IsCodec(codec, kDtmfCodecName)) {
1758 if (engine()->voe()->dtmf()->SetSendTelephoneEventPayloadType(
1759 channel, codec.id) == -1) {
1760 LOG_RTCERR2(SetSendTelephoneEventPayloadType, channel, codec.id);
1761 return false;
1762 }
1763 } else if (IsCodec(codec, kCnCodecName)) {
1764 // Turn voice activity detection/comfort noise on if supported. 1763 // Turn voice activity detection/comfort noise on if supported.
1765 // Set the wideband CN payload type appropriately. 1764 // Set the wideband CN payload type appropriately.
1766 // (narrowband always uses the static payload type 13). 1765 // (narrowband always uses the static payload type 13).
1767 webrtc::PayloadFrequencies cn_freq; 1766 webrtc::PayloadFrequencies cn_freq;
1768 switch (codec.clockrate) { 1767 switch (codec.clockrate) {
1769 case 8000: 1768 case 8000:
1770 cn_freq = webrtc::kFreq8000Hz; 1769 cn_freq = webrtc::kFreq8000Hz;
1771 break; 1770 break;
1772 case 16000: 1771 case 16000:
1773 cn_freq = webrtc::kFreq16000Hz; 1772 cn_freq = webrtc::kFreq16000Hz;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1808 } 1807 }
1809 } 1808 }
1810 } 1809 }
1811 } 1810 }
1812 return true; 1811 return true;
1813 } 1812 }
1814 1813
1815 bool WebRtcVoiceMediaChannel::SetSendCodecs( 1814 bool WebRtcVoiceMediaChannel::SetSendCodecs(
1816 const std::vector<AudioCodec>& codecs) { 1815 const std::vector<AudioCodec>& codecs) {
1817 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 1816 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1817 // TODO(solenberg): Validate input - that payload types don't overlap, are
1818 // within range, filter out codecs we don't support,
1819 // redundant codecs etc.
1818 1820
1819 dtmf_allowed_ = false; 1821 // Find the DTMF telephone event "codec" payload type.
1822 dtmf_payload_type_ = rtc::Optional<int>();
1820 for (const AudioCodec& codec : codecs) { 1823 for (const AudioCodec& codec : codecs) {
1821 // Find the DTMF telephone event "codec".
1822 if (IsCodec(codec, kDtmfCodecName)) { 1824 if (IsCodec(codec, kDtmfCodecName)) {
1823 dtmf_allowed_ = true; 1825 dtmf_payload_type_ = rtc::Optional<int>(codec.id);
1826 break;
1824 } 1827 }
1825 } 1828 }
1826 1829
1827 // Cache the codecs in order to configure the channel created later. 1830 // Cache the codecs in order to configure the channel created later.
1828 send_codecs_ = codecs; 1831 send_codecs_ = codecs;
1829 for (const auto& ch : send_streams_) { 1832 for (const auto& ch : send_streams_) {
1830 if (!SetSendCodecs(ch.second->channel(), codecs)) { 1833 if (!SetSendCodecs(ch.second->channel(), codecs)) {
1831 return false; 1834 return false;
1832 } 1835 }
1833 } 1836 }
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after
2276 volume)) { 2279 volume)) {
2277 LOG_RTCERR2(SetChannelOutputVolumeScaling, ch_id, volume); 2280 LOG_RTCERR2(SetChannelOutputVolumeScaling, ch_id, volume);
2278 return false; 2281 return false;
2279 } 2282 }
2280 LOG(LS_INFO) << "SetOutputVolume to " << volume 2283 LOG(LS_INFO) << "SetOutputVolume to " << volume
2281 << " for channel " << ch_id << " and ssrc " << ssrc; 2284 << " for channel " << ch_id << " and ssrc " << ssrc;
2282 return true; 2285 return true;
2283 } 2286 }
2284 2287
2285 bool WebRtcVoiceMediaChannel::CanInsertDtmf() { 2288 bool WebRtcVoiceMediaChannel::CanInsertDtmf() {
2286 return dtmf_allowed_; 2289 return dtmf_payload_type_ ? true : false;
2287 } 2290 }
2288 2291
2289 bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc, int event, 2292 bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc, int event,
2290 int duration) { 2293 int duration) {
2291 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 2294 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2292 if (!dtmf_allowed_) { 2295 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::InsertDtmf";
2296 if (!dtmf_payload_type_) {
2293 return false; 2297 return false;
2294 } 2298 }
2295 2299
2296 // Send the event. 2300 // Figure out which WebRtcAudioSendStream to send the event on.
2297 int channel = -1; 2301 auto it = send_streams_.end();
2298 if (ssrc == 0) { 2302 if (ssrc == 0) {
2299 if (send_streams_.size() > 0) { 2303 it = send_streams_.begin();
2300 channel = send_streams_.begin()->second->channel();
2301 }
2302 } else { 2304 } else {
2303 channel = GetSendChannelId(ssrc); 2305 it = send_streams_.find(ssrc);
2304 } 2306 }
pthatcher1 2015/12/02 18:45:37 Does this work? audio it = ssrc ? send_streams_.f
the sun 2015/12/03 09:57:47 Nice one! Except "audio" is not a recognized C++
2305 if (channel == -1) { 2307 if (it == send_streams_.end()) {
2306 LOG(LS_WARNING) << "InsertDtmf - The specified ssrc " 2308 LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
2307 << ssrc << " is not in use.";
2308 return false; 2309 return false;
2309 } 2310 }
2310 // Send DTMF using out-of-band DTMF. ("true", as 3rd arg) 2311 if (event < kMinTelephoneEventCode ||
2311 if (engine()->voe()->dtmf()->SendTelephoneEvent( 2312 event > kMaxTelephoneEventCode) {
2312 channel, event, true, duration) == -1) { 2313 LOG(LS_WARNING) << "DTMF event code " << event << " out of range.";
2313 LOG_RTCERR4(SendTelephoneEvent, channel, event, true, duration);
2314 return false; 2314 return false;
2315 } 2315 }
2316 2316 if (duration < kMinTelephoneEventDuration ||
2317 return true; 2317 duration > kMaxTelephoneEventDuration) {
2318 LOG(LS_WARNING) << "DTMF event duration " << duration << " out of range.";
2319 return false;
2320 }
2321 return it->second->stream()->SendTelephoneEvent(*dtmf_payload_type_, event,
2322 duration);
2318 } 2323 }
2319 2324
2320 void WebRtcVoiceMediaChannel::OnPacketReceived( 2325 void WebRtcVoiceMediaChannel::OnPacketReceived(
2321 rtc::Buffer* packet, const rtc::PacketTime& packet_time) { 2326 rtc::Buffer* packet, const rtc::PacketTime& packet_time) {
2322 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 2327 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2323 2328
2324 uint32_t ssrc = 0; 2329 uint32_t ssrc = 0;
2325 if (!GetRtpSsrc(packet->data(), packet->size(), &ssrc)) { 2330 if (!GetRtpSsrc(packet->data(), packet->size(), &ssrc)) {
2326 return; 2331 return;
2327 } 2332 }
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after
2639 } 2644 }
2640 } else { 2645 } else {
2641 LOG(LS_INFO) << "Stopping playout for channel #" << channel; 2646 LOG(LS_INFO) << "Stopping playout for channel #" << channel;
2642 engine()->voe()->base()->StopPlayout(channel); 2647 engine()->voe()->base()->StopPlayout(channel);
2643 } 2648 }
2644 return true; 2649 return true;
2645 } 2650 }
2646 } // namespace cricket 2651 } // namespace cricket
2647 2652
2648 #endif // HAVE_WEBRTC_VOICE 2653 #endif // HAVE_WEBRTC_VOICE
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698