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

Side by Side Diff: webrtc/modules/rtp_rtcp/source/rtp_sender_audio.cc

Issue 2392883002: Multi frequency DTMF support - sender side (Closed)
Patch Set: WVoMC unittests for multi rate DTMF send 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) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 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
11 #include "webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h" 11 #include "webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h"
12 12
13 #include <string.h> 13 #include <string.h>
14 14
15 #include <memory> 15 #include <memory>
16 #include <utility> 16 #include <utility>
17 17
18 #include "webrtc/base/logging.h" 18 #include "webrtc/base/logging.h"
19 #include "webrtc/base/timeutils.h" 19 #include "webrtc/base/timeutils.h"
20 #include "webrtc/base/trace_event.h" 20 #include "webrtc/base/trace_event.h"
21 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" 21 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
22 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" 22 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
23 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h" 23 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h"
24 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" 24 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h"
25 25
26 namespace webrtc { 26 namespace webrtc {
27 27
28 static const int kDtmfFrequencyHz = 8000; 28 static const int kDtmfBaseRateHz = 8000;
29 29
30 RTPSenderAudio::RTPSenderAudio(Clock* clock, RTPSender* rtp_sender) 30 RTPSenderAudio::RTPSenderAudio(Clock* clock, RTPSender* rtp_sender)
31 : clock_(clock), 31 : clock_(clock),
32 rtp_sender_(rtp_sender), 32 rtp_sender_(rtp_sender) {}
33 packet_size_samples_(160),
34 dtmf_event_is_on_(false),
35 dtmf_event_first_packet_sent_(false),
36 dtmf_payload_type_(-1),
37 dtmf_timestamp_(0),
38 dtmf_key_(0),
39 dtmf_length_samples_(0),
40 dtmf_level_(0),
41 dtmf_time_last_sent_(0),
42 dtmf_timestamp_last_sent_(0),
43 inband_vad_active_(false),
44 cngnb_payload_type_(-1),
45 cngwb_payload_type_(-1),
46 cngswb_payload_type_(-1),
47 cngfb_payload_type_(-1),
48 last_payload_type_(-1),
49 audio_level_dbov_(0) {}
50 33
51 RTPSenderAudio::~RTPSenderAudio() {} 34 RTPSenderAudio::~RTPSenderAudio() {}
52 35
53 // set audio packet size, used to determine when it's time to send a DTMF packet 36 // set audio packet size, used to determine when it's time to send a DTMF packet
54 // in silence (CNG) 37 // in silence (CNG)
55 int32_t RTPSenderAudio::SetAudioPacketSize(uint16_t packet_size_samples) { 38 int32_t RTPSenderAudio::SetAudioPacketSize(uint16_t packet_size_samples) {
56 rtc::CritScope cs(&send_audio_critsect_); 39 rtc::CritScope cs(&send_audio_critsect_);
57 packet_size_samples_ = packet_size_samples; 40 packet_size_samples_ = packet_size_samples;
58 return 0; 41 return 0;
59 } 42 }
(...skipping 22 matching lines...) Expand all
82 cngfb_payload_type_ = payload_type; 65 cngfb_payload_type_ = payload_type;
83 break; 66 break;
84 default: 67 default:
85 return -1; 68 return -1;
86 } 69 }
87 } else if (RtpUtility::StringCompare(payloadName, "telephone-event", 15)) { 70 } else if (RtpUtility::StringCompare(payloadName, "telephone-event", 15)) {
88 rtc::CritScope cs(&send_audio_critsect_); 71 rtc::CritScope cs(&send_audio_critsect_);
89 // Don't add it to the list 72 // Don't add it to the list
90 // we dont want to allow send with a DTMF payloadtype 73 // we dont want to allow send with a DTMF payloadtype
91 dtmf_payload_type_ = payload_type; 74 dtmf_payload_type_ = payload_type;
75 // Frequency is ignored for DTMF - we're using the same RTP timestamp rate
76 // as the audio codec.
92 return 0; 77 return 0;
93 // The default timestamp rate is 8000 Hz, but other rates may be defined.
94 } 78 }
95 *payload = new RtpUtility::Payload; 79 *payload = new RtpUtility::Payload;
96 (*payload)->typeSpecific.Audio.frequency = frequency; 80 (*payload)->typeSpecific.Audio.frequency = frequency;
97 (*payload)->typeSpecific.Audio.channels = channels; 81 (*payload)->typeSpecific.Audio.channels = channels;
98 (*payload)->typeSpecific.Audio.rate = rate; 82 (*payload)->typeSpecific.Audio.rate = rate;
99 (*payload)->audio = true; 83 (*payload)->audio = true;
100 (*payload)->name[RTP_PAYLOAD_NAME_SIZE - 1] = '\0'; 84 (*payload)->name[RTP_PAYLOAD_NAME_SIZE - 1] = '\0';
101 strncpy((*payload)->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1); 85 strncpy((*payload)->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
102 return 0; 86 return 0;
103 } 87 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 return marker_bit; 129 return marker_bit;
146 } 130 }
147 131
148 bool RTPSenderAudio::SendAudio(FrameType frame_type, 132 bool RTPSenderAudio::SendAudio(FrameType frame_type,
149 int8_t payload_type, 133 int8_t payload_type,
150 uint32_t rtp_timestamp, 134 uint32_t rtp_timestamp,
151 const uint8_t* payload_data, 135 const uint8_t* payload_data,
152 size_t payload_size, 136 size_t payload_size,
153 const RTPFragmentationHeader* fragmentation) { 137 const RTPFragmentationHeader* fragmentation) {
154 // TODO(pwestin) Breakup function in smaller functions. 138 // TODO(pwestin) Breakup function in smaller functions.
155 uint16_t dtmf_length_ms = 0;
156 uint8_t key = 0;
157 uint8_t audio_level_dbov; 139 uint8_t audio_level_dbov;
158 int8_t dtmf_payload_type;
159 uint16_t packet_size_samples; 140 uint16_t packet_size_samples;
160 { 141 {
161 rtc::CritScope cs(&send_audio_critsect_); 142 rtc::CritScope cs(&send_audio_critsect_);
162 audio_level_dbov = audio_level_dbov_; 143 audio_level_dbov = audio_level_dbov_;
163 dtmf_payload_type = dtmf_payload_type_;
164 packet_size_samples = packet_size_samples_; 144 packet_size_samples = packet_size_samples_;
165 } 145 }
166 146
167 // Check if we have pending DTMFs to send 147 // Check if we have pending DTMFs to send
168 if (!dtmf_event_is_on_ && dtmf_queue_.PendingDTMF()) { 148 if (!dtmf_event_is_on_ && dtmf_queue_.PendingDTMF()) {
169 int64_t delaySinceLastDTMF = 149 int64_t delaySinceLastDTMF =
170 clock_->TimeInMilliseconds() - dtmf_time_last_sent_; 150 clock_->TimeInMilliseconds() - dtmf_time_last_sent_;
171 151
172 if (delaySinceLastDTMF > 100) { 152 if (delaySinceLastDTMF > 100) {
173 // New tone to play 153 // New tone to play
174 dtmf_timestamp_ = rtp_timestamp; 154 dtmf_timestamp_ = rtp_timestamp;
175 if (dtmf_queue_.NextDTMF(&key, &dtmf_length_ms, &dtmf_level_) >= 0) { 155 if (dtmf_queue_.NextDTMF(&dtmf_current_event_) >= 0) {
176 dtmf_event_first_packet_sent_ = false; 156 dtmf_event_first_packet_sent_ = false;
177 dtmf_key_ = key; 157 dtmf_length_samples_ =
178 dtmf_length_samples_ = (kDtmfFrequencyHz / 1000) * dtmf_length_ms; 158 (kDtmfBaseRateHz / 1000) * dtmf_current_event_.duration_ms;
179 dtmf_event_is_on_ = true; 159 dtmf_event_is_on_ = true;
180 } 160 }
181 } 161 }
182 } 162 }
183 163
184 // A source MAY send events and coded audio packets for the same time 164 // A source MAY send events and coded audio packets for the same time
185 // but we don't support it 165 // but we don't support it
186 if (dtmf_event_is_on_) { 166 if (dtmf_event_is_on_) {
187 if (frame_type == kEmptyFrame) { 167 if (frame_type == kEmptyFrame) {
188 // kEmptyFrame is used to drive the DTMF when in CN mode 168 // kEmptyFrame is used to drive the DTMF when in CN mode
(...skipping 15 matching lines...) Expand all
204 send = false; 184 send = false;
205 } 185 }
206 } else { 186 } else {
207 ended = true; 187 ended = true;
208 dtmf_event_is_on_ = false; 188 dtmf_event_is_on_ = false;
209 dtmf_time_last_sent_ = clock_->TimeInMilliseconds(); 189 dtmf_time_last_sent_ = clock_->TimeInMilliseconds();
210 } 190 }
211 if (send) { 191 if (send) {
212 if (dtmf_duration_samples > 0xffff) { 192 if (dtmf_duration_samples > 0xffff) {
213 // RFC 4733 2.5.2.3 Long-Duration Events 193 // RFC 4733 2.5.2.3 Long-Duration Events
214 SendTelephoneEventPacket(ended, dtmf_payload_type, dtmf_timestamp_, 194 SendTelephoneEventPacket(ended, dtmf_timestamp_,
215 static_cast<uint16_t>(0xffff), false); 195 static_cast<uint16_t>(0xffff), false);
216 196
217 // set new timestap for this segment 197 // set new timestap for this segment
218 dtmf_timestamp_ = rtp_timestamp; 198 dtmf_timestamp_ = rtp_timestamp;
219 dtmf_duration_samples -= 0xffff; 199 dtmf_duration_samples -= 0xffff;
220 dtmf_length_samples_ -= 0xffff; 200 dtmf_length_samples_ -= 0xffff;
221 201
222 return SendTelephoneEventPacket( 202 return SendTelephoneEventPacket(ended, dtmf_timestamp_,
223 ended, dtmf_payload_type, dtmf_timestamp_,
224 static_cast<uint16_t>(dtmf_duration_samples), false); 203 static_cast<uint16_t>(dtmf_duration_samples), false);
225 } else { 204 } else {
226 if (!SendTelephoneEventPacket(ended, dtmf_payload_type, dtmf_timestamp_, 205 if (!SendTelephoneEventPacket(ended, dtmf_timestamp_,
227 dtmf_duration_samples, 206 dtmf_duration_samples,
228 !dtmf_event_first_packet_sent_)) { 207 !dtmf_event_first_packet_sent_)) {
229 return false; 208 return false;
230 } 209 }
231 dtmf_event_first_packet_sent_ = true; 210 dtmf_event_first_packet_sent_ = true;
232 return true; 211 return true;
233 } 212 }
234 } 213 }
235 return true; 214 return true;
236 } 215 }
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 } 271 }
293 rtc::CritScope cs(&send_audio_critsect_); 272 rtc::CritScope cs(&send_audio_critsect_);
294 audio_level_dbov_ = level_dbov; 273 audio_level_dbov_ = level_dbov;
295 return 0; 274 return 0;
296 } 275 }
297 276
298 // Send a TelephoneEvent tone using RFC 2833 (4733) 277 // Send a TelephoneEvent tone using RFC 2833 (4733)
299 int32_t RTPSenderAudio::SendTelephoneEvent(uint8_t key, 278 int32_t RTPSenderAudio::SendTelephoneEvent(uint8_t key,
300 uint16_t time_ms, 279 uint16_t time_ms,
301 uint8_t level) { 280 uint8_t level) {
281 DTMFQueue::Event event;
302 { 282 {
303 rtc::CritScope lock(&send_audio_critsect_); 283 rtc::CritScope lock(&send_audio_critsect_);
304 if (dtmf_payload_type_ < 0) { 284 if (dtmf_payload_type_ < 0) {
305 // TelephoneEvent payloadtype not configured 285 // TelephoneEvent payloadtype not configured
306 return -1; 286 return -1;
307 } 287 }
288 event.payload_type = dtmf_payload_type_;
308 } 289 }
309 return dtmf_queue_.AddDTMF(key, time_ms, level); 290 event.key = key;
291 event.duration_ms = time_ms;
292 event.level = level;
293 return dtmf_queue_.AddDTMF(event);
310 } 294 }
311 295
312 bool RTPSenderAudio::SendTelephoneEventPacket(bool ended, 296 bool RTPSenderAudio::SendTelephoneEventPacket(bool ended,
313 int8_t dtmf_payload_type,
314 uint32_t dtmf_timestamp, 297 uint32_t dtmf_timestamp,
315 uint16_t duration, 298 uint16_t duration,
316 bool marker_bit) { 299 bool marker_bit) {
317 uint8_t send_count = 1; 300 uint8_t send_count = 1;
318 bool result = true; 301 bool result = true;
319 302
320 if (ended) { 303 if (ended) {
321 // resend last packet in an event 3 times 304 // resend last packet in an event 3 times
322 send_count = 3; 305 send_count = 3;
323 } 306 }
324 do { 307 do {
325 // Send DTMF data. 308 // Send DTMF data.
326 constexpr RtpPacketToSend::ExtensionManager* kNoExtensions = nullptr; 309 constexpr RtpPacketToSend::ExtensionManager* kNoExtensions = nullptr;
327 constexpr size_t kDtmfSize = 4; 310 constexpr size_t kDtmfSize = 4;
328 std::unique_ptr<RtpPacketToSend> packet( 311 std::unique_ptr<RtpPacketToSend> packet(
329 new RtpPacketToSend(kNoExtensions, kRtpHeaderSize + kDtmfSize)); 312 new RtpPacketToSend(kNoExtensions, kRtpHeaderSize + kDtmfSize));
330 packet->SetPayloadType(dtmf_payload_type); 313 packet->SetPayloadType(dtmf_current_event_.payload_type);
331 packet->SetMarker(marker_bit); 314 packet->SetMarker(marker_bit);
332 packet->SetSsrc(rtp_sender_->SSRC()); 315 packet->SetSsrc(rtp_sender_->SSRC());
333 packet->SetTimestamp(dtmf_timestamp); 316 packet->SetTimestamp(dtmf_timestamp);
334 packet->set_capture_time_ms(clock_->TimeInMilliseconds()); 317 packet->set_capture_time_ms(clock_->TimeInMilliseconds());
335 if (!rtp_sender_->AssignSequenceNumber(packet.get())) 318 if (!rtp_sender_->AssignSequenceNumber(packet.get()))
336 return false; 319 return false;
337 320
338 // Create DTMF data. 321 // Create DTMF data.
339 uint8_t* dtmfbuffer = packet->AllocatePayload(kDtmfSize); 322 uint8_t* dtmfbuffer = packet->AllocatePayload(kDtmfSize);
340 RTC_DCHECK(dtmfbuffer); 323 RTC_DCHECK(dtmfbuffer);
341 /* From RFC 2833: 324 /* From RFC 2833:
342 0 1 2 3 325 0 1 2 3
343 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 326 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
344 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 327 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
345 | event |E|R| volume | duration | 328 | event |E|R| volume | duration |
346 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 329 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
347 */ 330 */
348 // R bit always cleared 331 // R bit always cleared
349 uint8_t R = 0x00; 332 uint8_t R = 0x00;
350 uint8_t volume = dtmf_level_; 333 uint8_t volume = dtmf_current_event_.level;
351 334
352 // First packet un-ended 335 // First packet un-ended
353 uint8_t E = ended ? 0x80 : 0x00; 336 uint8_t E = ended ? 0x80 : 0x00;
354 337
355 // First byte is Event number, equals key number 338 // First byte is Event number, equals key number
356 dtmfbuffer[0] = dtmf_key_; 339 dtmfbuffer[0] = dtmf_current_event_.key;
357 dtmfbuffer[1] = E | R | volume; 340 dtmfbuffer[1] = E | R | volume;
358 ByteWriter<uint16_t>::WriteBigEndian(dtmfbuffer + 2, duration); 341 ByteWriter<uint16_t>::WriteBigEndian(dtmfbuffer + 2, duration);
359 342
360 TRACE_EVENT_INSTANT2( 343 TRACE_EVENT_INSTANT2(
361 TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "Audio::SendTelephoneEvent", 344 TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "Audio::SendTelephoneEvent",
362 "timestamp", packet->Timestamp(), "seqnum", packet->SequenceNumber()); 345 "timestamp", packet->Timestamp(), "seqnum", packet->SequenceNumber());
363 result = rtp_sender_->SendToNetwork(std::move(packet), kAllowRetransmission, 346 result = rtp_sender_->SendToNetwork(std::move(packet), kAllowRetransmission,
364 RtpPacketSender::kHighPriority); 347 RtpPacketSender::kHighPriority);
365 send_count--; 348 send_count--;
366 } while (send_count > 0 && result); 349 } while (send_count > 0 && result);
367 350
368 return result; 351 return result;
369 } 352 }
370 } // namespace webrtc 353 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698