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

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

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

Powered by Google App Engine
This is Rietveld 408576698