2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
11 #include "webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h"
13 #include <assert.h> //assert
14 #include <string.h> //memcpy
16 #include "webrtc/system_wrappers/interface/trace_event.h"
19 RTPSenderAudio::RTPSenderAudio(const int32_t id, Clock* clock,
20 RTPSender* rtpSender) :
23 _rtpSender(rtpSender),
24 _audioFeedbackCritsect(CriticalSectionWrapper::CreateCriticalSection()),
26 _sendAudioCritsect(CriticalSectionWrapper::CreateCriticalSection()),
28 _packetSizeSamples(160),
29 _dtmfEventIsOn(false),
30 _dtmfEventFirstPacketSent(false),
34 _dtmfLengthSamples(0),
37 _dtmfTimestampLastSent(0),
39 _inbandVADactive(false),
40 _cngNBPayloadType(-1),
41 _cngWBPayloadType(-1),
42 _cngSWBPayloadType(-1),
43 _cngFBPayloadType(-1),
48 RTPSenderAudio::~RTPSenderAudio()
50 delete _sendAudioCritsect;
51 delete _audioFeedbackCritsect;
55 RTPSenderAudio::RegisterAudioCallback(RtpAudioFeedback* messagesCallback)
57 CriticalSectionScoped cs(_audioFeedbackCritsect);
58 _audioFeedback = messagesCallback;
63 RTPSenderAudio::SetAudioFrequency(const uint32_t f)
65 CriticalSectionScoped cs(_sendAudioCritsect);
70 RTPSenderAudio::AudioFrequency() const
72 CriticalSectionScoped cs(_sendAudioCritsect);
76 // set audio packet size, used to determine when it's time to send a DTMF packet in silence (CNG)
78 RTPSenderAudio::SetAudioPacketSize(const uint16_t packetSizeSamples)
80 CriticalSectionScoped cs(_sendAudioCritsect);
82 _packetSizeSamples = packetSizeSamples;
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,
92 RtpUtility::Payload*& payload) {
93 CriticalSectionScoped cs(_sendAudioCritsect);
95 if (RtpUtility::StringCompare(payloadName, "cn", 2)) {
96 // we can have multiple CNG payload types
97 if (frequency == 8000) {
98 _cngNBPayloadType = payloadType;
100 } else if (frequency == 16000) {
101 _cngWBPayloadType = payloadType;
103 } else if (frequency == 32000) {
104 _cngSWBPayloadType = payloadType;
106 } else if (frequency == 48000) {
107 _cngFBPayloadType = payloadType;
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;
118 // The default timestamp rate is 8000 Hz, but other rates may be defined.
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);
131 RTPSenderAudio::MarkerBit(const FrameType frameType,
132 const int8_t payloadType)
134 CriticalSectionScoped cs(_sendAudioCritsect);
136 // for audio true for first packet in a speech burst
137 bool markerBit = false;
138 if(_lastPayloadType != payloadType)
140 if(_cngNBPayloadType != -1)
142 // we have configured NB CNG
143 if(_cngNBPayloadType == payloadType)
145 // only set a marker bit when we change payload type to a non CNG
149 if(_cngWBPayloadType != -1)
151 // we have configured WB CNG
152 if(_cngWBPayloadType == payloadType)
154 // only set a marker bit when we change payload type to a non CNG
158 if(_cngSWBPayloadType != -1)
160 // we have configured SWB CNG
161 if(_cngSWBPayloadType == payloadType)
163 // only set a marker bit when we change payload type to a non CNG
167 if(_cngFBPayloadType != -1)
169 // we have configured SWB CNG
170 if(_cngFBPayloadType == payloadType)
172 // only set a marker bit when we change payload type to a non CNG
176 // payloadType differ
177 if(_lastPayloadType == -1)
179 if(frameType != kAudioFrameCN)
181 // first packet and NOT CNG
186 // first packet and CNG
187 _inbandVADactive = true;
191 // not first packet AND
193 // payloadType changed
195 // set a marker bit when we change payload type
199 // For G.723 G.729, AMR etc we can have inband VAD
200 if(frameType == kAudioFrameCN)
202 _inbandVADactive = true;
204 } else if(_inbandVADactive)
206 _inbandVADactive = false;
213 RTPSenderAudio::SendTelephoneEventActive(int8_t& telephoneEvent) const
217 telephoneEvent = _dtmfKey;
220 int64_t delaySinceLastDTMF = _clock->TimeInMilliseconds() -
222 if(delaySinceLastDTMF < 100)
224 telephoneEvent = _dtmfKey;
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;
245 // Check if we have pending DTMFs to send
246 if (!_dtmfEventIsOn && PendingDTMF()) {
247 CriticalSectionScoped cs(_sendAudioCritsect);
249 int64_t delaySinceLastDTMF = _clock->TimeInMilliseconds() -
252 if (delaySinceLastDTMF > 100) {
254 _dtmfTimestamp = captureTimeStamp;
255 if (NextDTMF(&key, &dtmfLengthMS, &_dtmfLevel) >= 0) {
256 _dtmfEventFirstPacketSent = false;
258 _dtmfLengthSamples = (_frequency / 1000) * dtmfLengthMS;
259 dtmfToneStarted = true;
260 _dtmfEventIsOn = true;
264 if (dtmfToneStarted) {
265 CriticalSectionScoped cs(_audioFeedbackCritsect);
266 if (_audioFeedback) {
267 _audioFeedback->OnPlayTelephoneEvent(_id, key, dtmfLengthMS, _dtmfLevel);
271 // A source MAY send events and coded audio packets for the same time
272 // but we don't support it
274 _sendAudioCritsect->Enter();
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
281 if (_packetSizeSamples > (captureTimeStamp - _dtmfTimestampLastSent)) {
282 // not time to send yet
283 _sendAudioCritsect->Leave();
287 _dtmfTimestampLastSent = captureTimeStamp;
288 uint32_t dtmfDurationSamples = captureTimeStamp - _dtmfTimestamp;
292 if (_dtmfLengthSamples > dtmfDurationSamples) {
293 if (dtmfDurationSamples <= 0) {
294 // Skip send packet at start, since we shouldn't use duration 0
299 _dtmfEventIsOn = false;
300 _dtmfTimeLastSent = _clock->TimeInMilliseconds();
302 // don't hold the critsect while calling SendTelephoneEventPacket
303 _sendAudioCritsect->Leave();
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);
310 // set new timestap for this segment
311 _dtmfTimestamp = captureTimeStamp;
312 dtmfDurationSamples -= 0xffff;
313 _dtmfLengthSamples -= 0xffff;
315 return SendTelephoneEventPacket(
318 static_cast<uint16_t>(dtmfDurationSamples),
321 // set markerBit on the first packet in the burst
322 _dtmfEventFirstPacketSent = true;
323 return SendTelephoneEventPacket(
326 static_cast<uint16_t>(dtmfDurationSamples),
327 !_dtmfEventFirstPacketSent);
332 _sendAudioCritsect->Leave();
334 if (payloadSize == 0 || payloadData == NULL) {
335 if (frameType == kFrameEmpty) {
336 // we don't send empty audio RTP packets
337 // no error since we use it to drive DTMF when we use VAD
342 uint8_t dataBuffer[IP_PACKET_SIZE];
343 bool markerBit = MarkerBit(frameType, payloadType);
345 int32_t rtpHeaderLength = 0;
346 uint16_t timestampOffset = 0;
348 if (_REDPayloadType >= 0 && fragmentation && !markerBit &&
349 fragmentation->fragmentationVectorSize > 1) {
350 // have we configured RED? use its payload type
351 // we need to get the current timestamp to calc the diff
352 uint32_t oldTimeStamp = _rtpSender->Timestamp();
353 rtpHeaderLength = _rtpSender->BuildRTPheader(dataBuffer, _REDPayloadType,
354 markerBit, captureTimeStamp,
355 _clock->TimeInMilliseconds());
357 timestampOffset = uint16_t(_rtpSender->Timestamp() - oldTimeStamp);
359 rtpHeaderLength = _rtpSender->BuildRTPheader(dataBuffer, payloadType,
360 markerBit, captureTimeStamp,
361 _clock->TimeInMilliseconds());
363 if (rtpHeaderLength <= 0) {
366 if (maxPayloadLength < (rtpHeaderLength + payloadSize)) {
367 // Too large payload buffer.
371 CriticalSectionScoped cs(_sendAudioCritsect);
372 if (_REDPayloadType >= 0 && // Have we configured RED?
374 fragmentation->fragmentationVectorSize > 1 &&
376 if (timestampOffset <= 0x3fff) {
377 if(fragmentation->fragmentationVectorSize != 2) {
378 // we only support 2 codecs when using RED
381 // only 0x80 if we have multiple blocks
382 dataBuffer[rtpHeaderLength++] = 0x80 +
383 fragmentation->fragmentationPlType[1];
384 uint32_t blockLength = fragmentation->fragmentationLength[1];
386 // sanity blockLength
387 if(blockLength > 0x3ff) { // block length 10 bits 1023 bytes
390 uint32_t REDheader = (timestampOffset << 10) + blockLength;
391 RtpUtility::AssignUWord24ToBuffer(dataBuffer + rtpHeaderLength,
393 rtpHeaderLength += 3;
395 dataBuffer[rtpHeaderLength++] = fragmentation->fragmentationPlType[0];
397 memcpy(dataBuffer+rtpHeaderLength,
398 payloadData + fragmentation->fragmentationOffset[1],
399 fragmentation->fragmentationLength[1]);
401 // copy the normal data
402 memcpy(dataBuffer+rtpHeaderLength +
403 fragmentation->fragmentationLength[1],
404 payloadData + fragmentation->fragmentationOffset[0],
405 fragmentation->fragmentationLength[0]);
407 payloadSize = static_cast<uint16_t>(
408 fragmentation->fragmentationLength[0] +
409 fragmentation->fragmentationLength[1]);
411 // silence for too long send only new data
412 dataBuffer[rtpHeaderLength++] = fragmentation->fragmentationPlType[0];
413 memcpy(dataBuffer+rtpHeaderLength,
414 payloadData + fragmentation->fragmentationOffset[0],
415 fragmentation->fragmentationLength[0]);
417 payloadSize = static_cast<uint16_t>(
418 fragmentation->fragmentationLength[0]);
421 if (fragmentation && fragmentation->fragmentationVectorSize > 0) {
422 // use the fragment info if we have one
423 dataBuffer[rtpHeaderLength++] = fragmentation->fragmentationPlType[0];
424 memcpy( dataBuffer+rtpHeaderLength,
425 payloadData + fragmentation->fragmentationOffset[0],
426 fragmentation->fragmentationLength[0]);
428 payloadSize = static_cast<uint16_t>(
429 fragmentation->fragmentationLength[0]);
431 memcpy(dataBuffer+rtpHeaderLength, payloadData, payloadSize);
434 _lastPayloadType = payloadType;
436 // Update audio level extension, if included.
438 uint16_t packetSize = payloadSize + rtpHeaderLength;
439 RtpUtility::RtpHeaderParser rtp_parser(dataBuffer, packetSize);
440 RTPHeader rtp_header;
441 rtp_parser.Parse(rtp_header);
442 _rtpSender->UpdateAudioLevel(dataBuffer, packetSize, rtp_header,
443 (frameType == kAudioFrameSpeech),
446 } // end critical section
447 TRACE_EVENT_ASYNC_END2("webrtc", "Audio", captureTimeStamp,
448 "timestamp", _rtpSender->Timestamp(),
449 "seqnum", _rtpSender->SequenceNumber());
450 return _rtpSender->SendToNetwork(dataBuffer,
452 static_cast<uint16_t>(rtpHeaderLength),
454 kAllowRetransmission,
455 PacedSender::kHighPriority);
458 // Audio level magnitude and voice activity flag are set for each RTP packet
460 RTPSenderAudio::SetAudioLevel(const uint8_t level_dBov)
462 if (level_dBov > 127)
466 CriticalSectionScoped cs(_sendAudioCritsect);
467 _audioLevel_dBov = level_dBov;
471 // Set payload type for Redundant Audio Data RFC 2198
473 RTPSenderAudio::SetRED(const int8_t payloadType)
475 if(payloadType < -1 )
479 _REDPayloadType = payloadType;
483 // Get payload type for Redundant Audio Data RFC 2198
485 RTPSenderAudio::RED(int8_t& payloadType) const
487 if(_REDPayloadType == -1)
492 payloadType = _REDPayloadType;
496 // Send a TelephoneEvent tone using RFC 2833 (4733)
498 RTPSenderAudio::SendTelephoneEvent(const uint8_t key,
499 const uint16_t time_ms,
502 // DTMF is protected by its own critsect
503 if(_dtmfPayloadType < 0)
505 // TelephoneEvent payloadtype not configured
508 return AddDTMF(key, time_ms, level);
512 RTPSenderAudio::SendTelephoneEventPacket(const bool ended,
513 const uint32_t dtmfTimeStamp,
514 const uint16_t duration,
515 const bool markerBit)
517 uint8_t dtmfbuffer[IP_PACKET_SIZE];
518 uint8_t sendCount = 1;
523 // resend last packet in an event 3 times
528 _sendAudioCritsect->Enter();
531 _rtpSender->BuildRTPheader(dtmfbuffer, _dtmfPayloadType, markerBit,
532 dtmfTimeStamp, _clock->TimeInMilliseconds());
534 // reset CSRC and X bit
535 dtmfbuffer[0] &= 0xe0;
541 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
542 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
543 | event |E|R| volume | duration |
544 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
546 // R bit always cleared
548 uint8_t volume = _dtmfLevel;
550 // First packet un-ended
558 // First byte is Event number, equals key number
559 dtmfbuffer[12] = _dtmfKey;
560 dtmfbuffer[13] = E|R|volume;
561 RtpUtility::AssignUWord16ToBuffer(dtmfbuffer + 14, duration);
563 _sendAudioCritsect->Leave();
564 TRACE_EVENT_INSTANT2("webrtc_rtp",
565 "Audio::SendTelephoneEvent",
566 "timestamp", dtmfTimeStamp,
567 "seqnum", _rtpSender->SequenceNumber());
568 retVal = _rtpSender->SendToNetwork(dtmfbuffer, 4, 12, -1,
569 kAllowRetransmission,
570 PacedSender::kHighPriority);
573 }while (sendCount > 0 && retVal == 0);
577 } // namespace webrtc