• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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