1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h"
12
13 #include <assert.h> //assert
14 #include <string.h> //memcpy
15
16 #include "webrtc/system_wrappers/interface/trace_event.h"
17
18 namespace webrtc {
RTPSenderAudio(const int32_t id,Clock * clock,RTPSender * rtpSender)19 RTPSenderAudio::RTPSenderAudio(const int32_t id, Clock* clock,
20 RTPSender* rtpSender) :
21 _id(id),
22 _clock(clock),
23 _rtpSender(rtpSender),
24 _audioFeedbackCritsect(CriticalSectionWrapper::CreateCriticalSection()),
25 _audioFeedback(NULL),
26 _sendAudioCritsect(CriticalSectionWrapper::CreateCriticalSection()),
27 _frequency(8000),
28 _packetSizeSamples(160),
29 _dtmfEventIsOn(false),
30 _dtmfEventFirstPacketSent(false),
31 _dtmfPayloadType(-1),
32 _dtmfTimestamp(0),
33 _dtmfKey(0),
34 _dtmfLengthSamples(0),
35 _dtmfLevel(0),
36 _dtmfTimeLastSent(0),
37 _dtmfTimestampLastSent(0),
38 _REDPayloadType(-1),
39 _inbandVADactive(false),
40 _cngNBPayloadType(-1),
41 _cngWBPayloadType(-1),
42 _cngSWBPayloadType(-1),
43 _cngFBPayloadType(-1),
44 _lastPayloadType(-1),
45 _audioLevel_dBov(0) {
46 };
47
~RTPSenderAudio()48 RTPSenderAudio::~RTPSenderAudio()
49 {
50 delete _sendAudioCritsect;
51 delete _audioFeedbackCritsect;
52 }
53
54 int32_t
RegisterAudioCallback(RtpAudioFeedback * messagesCallback)55 RTPSenderAudio::RegisterAudioCallback(RtpAudioFeedback* messagesCallback)
56 {
57 CriticalSectionScoped cs(_audioFeedbackCritsect);
58 _audioFeedback = messagesCallback;
59 return 0;
60 }
61
62 void
SetAudioFrequency(const uint32_t f)63 RTPSenderAudio::SetAudioFrequency(const uint32_t f)
64 {
65 CriticalSectionScoped cs(_sendAudioCritsect);
66 _frequency = f;
67 }
68
69 int
AudioFrequency() const70 RTPSenderAudio::AudioFrequency() const
71 {
72 CriticalSectionScoped cs(_sendAudioCritsect);
73 return _frequency;
74 }
75
76 // set audio packet size, used to determine when it's time to send a DTMF packet in silence (CNG)
77 int32_t
SetAudioPacketSize(const uint16_t packetSizeSamples)78 RTPSenderAudio::SetAudioPacketSize(const uint16_t packetSizeSamples)
79 {
80 CriticalSectionScoped cs(_sendAudioCritsect);
81
82 _packetSizeSamples = packetSizeSamples;
83 return 0;
84 }
85
RegisterAudioPayload(const char payloadName[RTP_PAYLOAD_NAME_SIZE],const int8_t payloadType,const uint32_t frequency,const uint8_t channels,const uint32_t rate,RtpUtility::Payload * & payload)86 int32_t RTPSenderAudio::RegisterAudioPayload(
87 const char payloadName[RTP_PAYLOAD_NAME_SIZE],
88 const int8_t payloadType,
89 const uint32_t frequency,
90 const uint8_t channels,
91 const uint32_t rate,
92 RtpUtility::Payload*& payload) {
93 CriticalSectionScoped cs(_sendAudioCritsect);
94
95 if (RtpUtility::StringCompare(payloadName, "cn", 2)) {
96 // we can have multiple CNG payload types
97 if (frequency == 8000) {
98 _cngNBPayloadType = payloadType;
99
100 } else if (frequency == 16000) {
101 _cngWBPayloadType = payloadType;
102
103 } else if (frequency == 32000) {
104 _cngSWBPayloadType = payloadType;
105
106 } else if (frequency == 48000) {
107 _cngFBPayloadType = payloadType;
108
109 } else {
110 return -1;
111 }
112 }
113 if (RtpUtility::StringCompare(payloadName, "telephone-event", 15)) {
114 // Don't add it to the list
115 // we dont want to allow send with a DTMF payloadtype
116 _dtmfPayloadType = payloadType;
117 return 0;
118 // The default timestamp rate is 8000 Hz, but other rates may be defined.
119 }
120 payload = new RtpUtility::Payload;
121 payload->typeSpecific.Audio.frequency = frequency;
122 payload->typeSpecific.Audio.channels = channels;
123 payload->typeSpecific.Audio.rate = rate;
124 payload->audio = true;
125 payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
126 strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
127 return 0;
128 }
129
130 bool
MarkerBit(const FrameType frameType,const int8_t payloadType)131 RTPSenderAudio::MarkerBit(const FrameType frameType,
132 const int8_t payloadType)
133 {
134 CriticalSectionScoped cs(_sendAudioCritsect);
135
136 // for audio true for first packet in a speech burst
137 bool markerBit = false;
138 if(_lastPayloadType != payloadType)
139 {
140 if(_cngNBPayloadType != -1)
141 {
142 // we have configured NB CNG
143 if(_cngNBPayloadType == payloadType)
144 {
145 // only set a marker bit when we change payload type to a non CNG
146 return false;
147 }
148 }
149 if(_cngWBPayloadType != -1)
150 {
151 // we have configured WB CNG
152 if(_cngWBPayloadType == payloadType)
153 {
154 // only set a marker bit when we change payload type to a non CNG
155 return false;
156 }
157 }
158 if(_cngSWBPayloadType != -1)
159 {
160 // we have configured SWB CNG
161 if(_cngSWBPayloadType == payloadType)
162 {
163 // only set a marker bit when we change payload type to a non CNG
164 return false;
165 }
166 }
167 if(_cngFBPayloadType != -1)
168 {
169 // we have configured SWB CNG
170 if(_cngFBPayloadType == payloadType)
171 {
172 // only set a marker bit when we change payload type to a non CNG
173 return false;
174 }
175 }
176 // payloadType differ
177 if(_lastPayloadType == -1)
178 {
179 if(frameType != kAudioFrameCN)
180 {
181 // first packet and NOT CNG
182 return true;
183
184 }else
185 {
186 // first packet and CNG
187 _inbandVADactive = true;
188 return false;
189 }
190 }
191 // not first packet AND
192 // not CNG AND
193 // payloadType changed
194
195 // set a marker bit when we change payload type
196 markerBit = true;
197 }
198
199 // For G.723 G.729, AMR etc we can have inband VAD
200 if(frameType == kAudioFrameCN)
201 {
202 _inbandVADactive = true;
203
204 } else if(_inbandVADactive)
205 {
206 _inbandVADactive = false;
207 markerBit = true;
208 }
209 return markerBit;
210 }
211
212 bool
SendTelephoneEventActive(int8_t & telephoneEvent) const213 RTPSenderAudio::SendTelephoneEventActive(int8_t& telephoneEvent) const
214 {
215 if(_dtmfEventIsOn)
216 {
217 telephoneEvent = _dtmfKey;
218 return true;
219 }
220 int64_t delaySinceLastDTMF = _clock->TimeInMilliseconds() -
221 _dtmfTimeLastSent;
222 if(delaySinceLastDTMF < 100)
223 {
224 telephoneEvent = _dtmfKey;
225 return true;
226 }
227 telephoneEvent = -1;
228 return false;
229 }
230
SendAudio(const FrameType frameType,const int8_t payloadType,const uint32_t captureTimeStamp,const uint8_t * payloadData,const uint32_t dataSize,const RTPFragmentationHeader * fragmentation)231 int32_t RTPSenderAudio::SendAudio(
232 const FrameType frameType,
233 const int8_t payloadType,
234 const uint32_t captureTimeStamp,
235 const uint8_t* payloadData,
236 const uint32_t dataSize,
237 const RTPFragmentationHeader* fragmentation) {
238 // TODO(pwestin) Breakup function in smaller functions.
239 uint16_t payloadSize = static_cast<uint16_t>(dataSize);
240 uint16_t maxPayloadLength = _rtpSender->MaxPayloadLength();
241 bool dtmfToneStarted = false;
242 uint16_t dtmfLengthMS = 0;
243 uint8_t key = 0;
244
245 // Check if we have pending DTMFs to send
246 if (!_dtmfEventIsOn && PendingDTMF()) {
247 CriticalSectionScoped cs(_sendAudioCritsect);
248
249 int64_t delaySinceLastDTMF = _clock->TimeInMilliseconds() -
250 _dtmfTimeLastSent;
251
252 if (delaySinceLastDTMF > 100) {
253 // New tone to play
254 _dtmfTimestamp = captureTimeStamp;
255 if (NextDTMF(&key, &dtmfLengthMS, &_dtmfLevel) >= 0) {
256 _dtmfEventFirstPacketSent = false;
257 _dtmfKey = key;
258 _dtmfLengthSamples = (_frequency / 1000) * dtmfLengthMS;
259 dtmfToneStarted = true;
260 _dtmfEventIsOn = true;
261 }
262 }
263 }
264 if (dtmfToneStarted) {
265 CriticalSectionScoped cs(_audioFeedbackCritsect);
266 if (_audioFeedback) {
267 _audioFeedback->OnPlayTelephoneEvent(_id, key, dtmfLengthMS, _dtmfLevel);
268 }
269 }
270
271 // A source MAY send events and coded audio packets for the same time
272 // but we don't support it
273 {
274 _sendAudioCritsect->Enter();
275
276 if (_dtmfEventIsOn) {
277 if (frameType == kFrameEmpty) {
278 // kFrameEmpty is used to drive the DTMF when in CN mode
279 // it can be triggered more frequently than we want to send the
280 // DTMF packets.
281 if (_packetSizeSamples > (captureTimeStamp - _dtmfTimestampLastSent)) {
282 // not time to send yet
283 _sendAudioCritsect->Leave();
284 return 0;
285 }
286 }
287 _dtmfTimestampLastSent = captureTimeStamp;
288 uint32_t dtmfDurationSamples = captureTimeStamp - _dtmfTimestamp;
289 bool ended = false;
290 bool send = true;
291
292 if (_dtmfLengthSamples > dtmfDurationSamples) {
293 if (dtmfDurationSamples <= 0) {
294 // Skip send packet at start, since we shouldn't use duration 0
295 send = false;
296 }
297 } else {
298 ended = true;
299 _dtmfEventIsOn = false;
300 _dtmfTimeLastSent = _clock->TimeInMilliseconds();
301 }
302 // don't hold the critsect while calling SendTelephoneEventPacket
303 _sendAudioCritsect->Leave();
304 if (send) {
305 if (dtmfDurationSamples > 0xffff) {
306 // RFC 4733 2.5.2.3 Long-Duration Events
307 SendTelephoneEventPacket(ended, _dtmfTimestamp,
308 static_cast<uint16_t>(0xffff), false);
309
310 // set new timestap for this segment
311 _dtmfTimestamp = captureTimeStamp;
312 dtmfDurationSamples -= 0xffff;
313 _dtmfLengthSamples -= 0xffff;
314
315 return SendTelephoneEventPacket(
316 ended,
317 _dtmfTimestamp,
318 static_cast<uint16_t>(dtmfDurationSamples),
319 false);
320 } else {
321 if (SendTelephoneEventPacket(
322 ended,
323 _dtmfTimestamp,
324 static_cast<uint16_t>(dtmfDurationSamples),
325 !_dtmfEventFirstPacketSent) != 0) {
326 return -1;
327 }
328 _dtmfEventFirstPacketSent = true;
329 return 0;
330 }
331 }
332 return 0;
333 }
334 _sendAudioCritsect->Leave();
335 }
336 if (payloadSize == 0 || payloadData == NULL) {
337 if (frameType == kFrameEmpty) {
338 // we don't send empty audio RTP packets
339 // no error since we use it to drive DTMF when we use VAD
340 return 0;
341 }
342 return -1;
343 }
344 uint8_t dataBuffer[IP_PACKET_SIZE];
345 bool markerBit = MarkerBit(frameType, payloadType);
346
347 int32_t rtpHeaderLength = 0;
348 uint16_t timestampOffset = 0;
349
350 if (_REDPayloadType >= 0 && fragmentation && !markerBit &&
351 fragmentation->fragmentationVectorSize > 1) {
352 // have we configured RED? use its payload type
353 // we need to get the current timestamp to calc the diff
354 uint32_t oldTimeStamp = _rtpSender->Timestamp();
355 rtpHeaderLength = _rtpSender->BuildRTPheader(dataBuffer, _REDPayloadType,
356 markerBit, captureTimeStamp,
357 _clock->TimeInMilliseconds());
358
359 timestampOffset = uint16_t(_rtpSender->Timestamp() - oldTimeStamp);
360 } else {
361 rtpHeaderLength = _rtpSender->BuildRTPheader(dataBuffer, payloadType,
362 markerBit, captureTimeStamp,
363 _clock->TimeInMilliseconds());
364 }
365 if (rtpHeaderLength <= 0) {
366 return -1;
367 }
368 if (maxPayloadLength < (rtpHeaderLength + payloadSize)) {
369 // Too large payload buffer.
370 return -1;
371 }
372 {
373 CriticalSectionScoped cs(_sendAudioCritsect);
374 if (_REDPayloadType >= 0 && // Have we configured RED?
375 fragmentation &&
376 fragmentation->fragmentationVectorSize > 1 &&
377 !markerBit) {
378 if (timestampOffset <= 0x3fff) {
379 if(fragmentation->fragmentationVectorSize != 2) {
380 // we only support 2 codecs when using RED
381 return -1;
382 }
383 // only 0x80 if we have multiple blocks
384 dataBuffer[rtpHeaderLength++] = 0x80 +
385 fragmentation->fragmentationPlType[1];
386 uint32_t blockLength = fragmentation->fragmentationLength[1];
387
388 // sanity blockLength
389 if(blockLength > 0x3ff) { // block length 10 bits 1023 bytes
390 return -1;
391 }
392 uint32_t REDheader = (timestampOffset << 10) + blockLength;
393 RtpUtility::AssignUWord24ToBuffer(dataBuffer + rtpHeaderLength,
394 REDheader);
395 rtpHeaderLength += 3;
396
397 dataBuffer[rtpHeaderLength++] = fragmentation->fragmentationPlType[0];
398 // copy the RED data
399 memcpy(dataBuffer+rtpHeaderLength,
400 payloadData + fragmentation->fragmentationOffset[1],
401 fragmentation->fragmentationLength[1]);
402
403 // copy the normal data
404 memcpy(dataBuffer+rtpHeaderLength +
405 fragmentation->fragmentationLength[1],
406 payloadData + fragmentation->fragmentationOffset[0],
407 fragmentation->fragmentationLength[0]);
408
409 payloadSize = static_cast<uint16_t>(
410 fragmentation->fragmentationLength[0] +
411 fragmentation->fragmentationLength[1]);
412 } else {
413 // silence for too long send only new data
414 dataBuffer[rtpHeaderLength++] = fragmentation->fragmentationPlType[0];
415 memcpy(dataBuffer+rtpHeaderLength,
416 payloadData + fragmentation->fragmentationOffset[0],
417 fragmentation->fragmentationLength[0]);
418
419 payloadSize = static_cast<uint16_t>(
420 fragmentation->fragmentationLength[0]);
421 }
422 } else {
423 if (fragmentation && fragmentation->fragmentationVectorSize > 0) {
424 // use the fragment info if we have one
425 dataBuffer[rtpHeaderLength++] = fragmentation->fragmentationPlType[0];
426 memcpy( dataBuffer+rtpHeaderLength,
427 payloadData + fragmentation->fragmentationOffset[0],
428 fragmentation->fragmentationLength[0]);
429
430 payloadSize = static_cast<uint16_t>(
431 fragmentation->fragmentationLength[0]);
432 } else {
433 memcpy(dataBuffer+rtpHeaderLength, payloadData, payloadSize);
434 }
435 }
436 _lastPayloadType = payloadType;
437
438 // Update audio level extension, if included.
439 {
440 uint16_t packetSize = payloadSize + rtpHeaderLength;
441 RtpUtility::RtpHeaderParser rtp_parser(dataBuffer, packetSize);
442 RTPHeader rtp_header;
443 rtp_parser.Parse(rtp_header);
444 _rtpSender->UpdateAudioLevel(dataBuffer, packetSize, rtp_header,
445 (frameType == kAudioFrameSpeech),
446 _audioLevel_dBov);
447 }
448 } // end critical section
449 TRACE_EVENT_ASYNC_END2("webrtc", "Audio", captureTimeStamp,
450 "timestamp", _rtpSender->Timestamp(),
451 "seqnum", _rtpSender->SequenceNumber());
452 return _rtpSender->SendToNetwork(dataBuffer,
453 payloadSize,
454 static_cast<uint16_t>(rtpHeaderLength),
455 -1,
456 kAllowRetransmission,
457 PacedSender::kHighPriority);
458 }
459
460 // Audio level magnitude and voice activity flag are set for each RTP packet
461 int32_t
SetAudioLevel(const uint8_t level_dBov)462 RTPSenderAudio::SetAudioLevel(const uint8_t level_dBov)
463 {
464 if (level_dBov > 127)
465 {
466 return -1;
467 }
468 CriticalSectionScoped cs(_sendAudioCritsect);
469 _audioLevel_dBov = level_dBov;
470 return 0;
471 }
472
473 // Set payload type for Redundant Audio Data RFC 2198
474 int32_t
SetRED(const int8_t payloadType)475 RTPSenderAudio::SetRED(const int8_t payloadType)
476 {
477 if(payloadType < -1 )
478 {
479 return -1;
480 }
481 _REDPayloadType = payloadType;
482 return 0;
483 }
484
485 // Get payload type for Redundant Audio Data RFC 2198
486 int32_t
RED(int8_t & payloadType) const487 RTPSenderAudio::RED(int8_t& payloadType) const
488 {
489 if(_REDPayloadType == -1)
490 {
491 // not configured
492 return -1;
493 }
494 payloadType = _REDPayloadType;
495 return 0;
496 }
497
498 // Send a TelephoneEvent tone using RFC 2833 (4733)
499 int32_t
SendTelephoneEvent(const uint8_t key,const uint16_t time_ms,const uint8_t level)500 RTPSenderAudio::SendTelephoneEvent(const uint8_t key,
501 const uint16_t time_ms,
502 const uint8_t level)
503 {
504 // DTMF is protected by its own critsect
505 if(_dtmfPayloadType < 0)
506 {
507 // TelephoneEvent payloadtype not configured
508 return -1;
509 }
510 return AddDTMF(key, time_ms, level);
511 }
512
513 int32_t
SendTelephoneEventPacket(const bool ended,const uint32_t dtmfTimeStamp,const uint16_t duration,const bool markerBit)514 RTPSenderAudio::SendTelephoneEventPacket(const bool ended,
515 const uint32_t dtmfTimeStamp,
516 const uint16_t duration,
517 const bool markerBit)
518 {
519 uint8_t dtmfbuffer[IP_PACKET_SIZE];
520 uint8_t sendCount = 1;
521 int32_t retVal = 0;
522
523 if(ended)
524 {
525 // resend last packet in an event 3 times
526 sendCount = 3;
527 }
528 do
529 {
530 _sendAudioCritsect->Enter();
531
532 //Send DTMF data
533 _rtpSender->BuildRTPheader(dtmfbuffer, _dtmfPayloadType, markerBit,
534 dtmfTimeStamp, _clock->TimeInMilliseconds());
535
536 // reset CSRC and X bit
537 dtmfbuffer[0] &= 0xe0;
538
539 //Create DTMF data
540 /* From RFC 2833:
541
542 0 1 2 3
543 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
544 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
545 | event |E|R| volume | duration |
546 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
547 */
548 // R bit always cleared
549 uint8_t R = 0x00;
550 uint8_t volume = _dtmfLevel;
551
552 // First packet un-ended
553 uint8_t E = 0x00;
554
555 if(ended)
556 {
557 E = 0x80;
558 }
559
560 // First byte is Event number, equals key number
561 dtmfbuffer[12] = _dtmfKey;
562 dtmfbuffer[13] = E|R|volume;
563 RtpUtility::AssignUWord16ToBuffer(dtmfbuffer + 14, duration);
564
565 _sendAudioCritsect->Leave();
566 TRACE_EVENT_INSTANT2("webrtc_rtp",
567 "Audio::SendTelephoneEvent",
568 "timestamp", dtmfTimeStamp,
569 "seqnum", _rtpSender->SequenceNumber());
570 retVal = _rtpSender->SendToNetwork(dtmfbuffer, 4, 12, -1,
571 kAllowRetransmission,
572 PacedSender::kHighPriority);
573 sendCount--;
574
575 }while (sendCount > 0 && retVal == 0);
576
577 return retVal;
578 }
579 } // namespace webrtc
580