blob: 3136b27d1146b9099313674dc82b1e7f26e09e48 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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 <cstdlib> // srand
12
13#include "rtp_sender.h"
14
15#include "critical_section_wrapper.h"
16#include "trace.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000017
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +000018#include "rtp_packet_history.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000019#include "rtp_sender_audio.h"
20#include "rtp_sender_video.h"
21
22namespace webrtc {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +000023RTPSender::RTPSender(const WebRtc_Word32 id,
24 const bool audio,
25 RtpRtcpClock* clock) :
26 Bitrate(clock),
niklase@google.com470e71d2011-07-07 08:21:25 +000027 _id(id),
28 _audioConfigured(audio),
29 _audio(NULL),
30 _video(NULL),
henrike@webrtc.org65573f22011-12-13 19:17:27 +000031 _sendCritsect(CriticalSectionWrapper::CreateCriticalSection()),
32 _transportCritsect(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000033
34 _transport(NULL),
35
36 _sendingMedia(true), // Default to sending media
37
38 _maxPayloadLength(IP_PACKET_SIZE-28), // default is IP/UDP
39 _targetSendBitrate(0),
40 _packetOverHead(28),
41
42 _payloadType(-1),
43 _payloadTypeMap(),
44
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +000045 _rtpHeaderExtensionMap(),
46 _transmissionTimeOffset(0),
47
niklase@google.com470e71d2011-07-07 08:21:25 +000048 // NACK
49 _nackByteCountTimes(),
50 _nackByteCount(),
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +000051 _nackBitrate(clock),
niklase@google.com470e71d2011-07-07 08:21:25 +000052
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +000053 _packetHistory(new RTPPacketHistory(clock)),
54 _sendBucket(),
55 _timeLastSendToNetworkUpdate(clock->GetTimeInMS()),
56 _transmissionSmoothing(false),
57
niklase@google.com470e71d2011-07-07 08:21:25 +000058 // statistics
59 _packetsSent(0),
60 _payloadBytesSent(0),
61
62 // RTP variables
63 _startTimeStampForced(false),
64 _startTimeStamp(0),
65 _ssrcDB(*SSRCDatabase::GetSSRCDatabase()),
66 _remoteSSRC(0),
67 _sequenceNumberForced(false),
68 _sequenceNumber(0),
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +000069 _sequenceNumberRTX(0),
niklase@google.com470e71d2011-07-07 08:21:25 +000070 _ssrcForced(false),
71 _ssrc(0),
72 _timeStamp(0),
73 _CSRCs(0),
74 _CSRC(),
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +000075 _includeCSRCs(true),
76 _RTX(false),
77 _ssrcRTX(0)
niklase@google.com470e71d2011-07-07 08:21:25 +000078{
79 memset(_nackByteCountTimes, 0, sizeof(_nackByteCountTimes));
80 memset(_nackByteCount, 0, sizeof(_nackByteCount));
81
82 memset(_CSRC, 0, sizeof(_CSRC));
83
84 // we need to seed the random generator, otherwise we get 26500 each time, hardly a random value :)
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +000085 srand( (WebRtc_UWord32)_clock.GetTimeInMS() );
niklase@google.com470e71d2011-07-07 08:21:25 +000086
87 _ssrc = _ssrcDB.CreateSSRC(); // can't be 0
88
89 if(audio)
90 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +000091 _audio = new RTPSenderAudio(id, &_clock, this);
niklase@google.com470e71d2011-07-07 08:21:25 +000092 } else
93 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +000094 _video = new RTPSenderVideo(id, &_clock, this);
niklase@google.com470e71d2011-07-07 08:21:25 +000095 }
96 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
97}
98
pwestin@webrtc.org00741872012-01-19 15:56:10 +000099RTPSender::~RTPSender() {
100 if(_remoteSSRC != 0) {
101 _ssrcDB.ReturnSSRC(_remoteSSRC);
102 }
103 _ssrcDB.ReturnSSRC(_ssrc);
niklase@google.com470e71d2011-07-07 08:21:25 +0000104
pwestin@webrtc.org00741872012-01-19 15:56:10 +0000105 SSRCDatabase::ReturnSSRCDatabase();
106 delete _sendCritsect;
107 delete _transportCritsect;
108 while (!_payloadTypeMap.empty()) {
109 std::map<WebRtc_Word8, ModuleRTPUtility::Payload*>::iterator it =
110 _payloadTypeMap.begin();
111 delete it->second;
112 _payloadTypeMap.erase(it);
113 }
114 delete _packetHistory;
115 delete _audio;
116 delete _video;
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000117
pwestin@webrtc.org00741872012-01-19 15:56:10 +0000118 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id, "%s deleted", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000119}
120
121WebRtc_Word32
122RTPSender::Init(const WebRtc_UWord32 remoteSSRC)
123{
124 CriticalSectionScoped cs(_sendCritsect);
125
126 // reset to default generation
127 _ssrcForced = false;
128 _startTimeStampForced = false;
129
130 // register a remote SSRC if we have it to avoid collisions
131 if(remoteSSRC != 0)
132 {
133 if(_ssrc == remoteSSRC)
134 {
135 // collision detected
136 _ssrc = _ssrcDB.CreateSSRC(); // can't be 0
137 }
138 _remoteSSRC = remoteSSRC;
139 _ssrcDB.RegisterSSRC(remoteSSRC);
140 }
141 _sequenceNumber = rand() / (RAND_MAX / MAX_INIT_RTP_SEQ_NUMBER);
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000142 _sequenceNumberRTX = rand() / (RAND_MAX / MAX_INIT_RTP_SEQ_NUMBER);
niklase@google.com470e71d2011-07-07 08:21:25 +0000143 _packetsSent = 0;
144 _payloadBytesSent = 0;
145 _packetOverHead = 28;
146
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000147 _rtpHeaderExtensionMap.Erase();
148
pwestin@webrtc.org00741872012-01-19 15:56:10 +0000149 while (!_payloadTypeMap.empty()) {
150 std::map<WebRtc_Word8, ModuleRTPUtility::Payload*>::iterator it =
151 _payloadTypeMap.begin();
152 delete it->second;
153 _payloadTypeMap.erase(it);
154 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000155
156 memset(_CSRC, 0, sizeof(_CSRC));
157
158 memset(_nackByteCount, 0, sizeof(_nackByteCount));
159 memset(_nackByteCountTimes, 0, sizeof(_nackByteCountTimes));
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +0000160 _nackBitrate.Init();
niklase@google.com470e71d2011-07-07 08:21:25 +0000161
162 SetStorePacketsStatus(false, 0);
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000163 _sendBucket.Reset();
niklase@google.com470e71d2011-07-07 08:21:25 +0000164
165 Bitrate::Init();
166
167 if(_audioConfigured)
168 {
169 _audio->Init();
170 } else
171 {
172 _video->Init();
173 }
174 return(0);
175}
176
177void
178RTPSender::ChangeUniqueId(const WebRtc_Word32 id)
179{
180 _id = id;
181 if(_audioConfigured)
182 {
183 _audio->ChangeUniqueId(id);
184 } else
185 {
186 _video->ChangeUniqueId(id);
187 }
188}
189
190WebRtc_Word32
191RTPSender::SetTargetSendBitrate(const WebRtc_UWord32 bits)
192{
193 _targetSendBitrate = (WebRtc_UWord16)(bits/1000);
194 return 0;
195}
196
197WebRtc_UWord16
198RTPSender::TargetSendBitrateKbit() const
199{
200 return _targetSendBitrate;
201}
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +0000202
niklase@google.com470e71d2011-07-07 08:21:25 +0000203WebRtc_UWord16
204RTPSender::ActualSendBitrateKbit() const
205{
206 return (WebRtc_UWord16) (Bitrate::BitrateNow()/1000);
207}
208
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +0000209WebRtc_UWord32
stefan@webrtc.orgfbea4e52011-10-27 16:08:29 +0000210RTPSender::VideoBitrateSent() const {
211 if (_video)
212 return _video->VideoBitrateSent();
213 else
214 return 0;
215}
216
217WebRtc_UWord32
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +0000218RTPSender::FecOverheadRate() const {
stefan@webrtc.orgfbea4e52011-10-27 16:08:29 +0000219 if (_video)
220 return _video->FecOverheadRate();
221 else
222 return 0;
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +0000223}
224
225WebRtc_UWord32
226RTPSender::NackOverheadRate() const {
227 return _nackBitrate.BitrateLast();
228}
229
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000230WebRtc_Word32
231RTPSender::SetTransmissionTimeOffset(
232 const WebRtc_Word32 transmissionTimeOffset)
233{
234 if (transmissionTimeOffset > (0x800000 - 1) ||
235 transmissionTimeOffset < -(0x800000 - 1)) // Word24
236 {
237 return -1;
238 }
239 CriticalSectionScoped cs(_sendCritsect);
240 _transmissionTimeOffset = transmissionTimeOffset;
241 return 0;
242}
243
244WebRtc_Word32
245RTPSender::RegisterRtpHeaderExtension(const RTPExtensionType type,
246 const WebRtc_UWord8 id)
247{
248 CriticalSectionScoped cs(_sendCritsect);
249 return _rtpHeaderExtensionMap.Register(type, id);
250}
251
252WebRtc_Word32
253RTPSender::DeregisterRtpHeaderExtension(const RTPExtensionType type)
254{
255 CriticalSectionScoped cs(_sendCritsect);
256 return _rtpHeaderExtensionMap.Deregister(type);
257}
258
259WebRtc_UWord16
260RTPSender::RtpHeaderExtensionTotalLength() const
261{
262 CriticalSectionScoped cs(_sendCritsect);
263 return _rtpHeaderExtensionMap.GetTotalLengthInBytes();
264}
265
niklase@google.com470e71d2011-07-07 08:21:25 +0000266//can be called multiple times
pwestin@webrtc.org00741872012-01-19 15:56:10 +0000267WebRtc_Word32 RTPSender::RegisterPayload(
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000268 const char payloadName[RTP_PAYLOAD_NAME_SIZE],
pwestin@webrtc.org00741872012-01-19 15:56:10 +0000269 const WebRtc_Word8 payloadNumber,
270 const WebRtc_UWord32 frequency,
271 const WebRtc_UWord8 channels,
272 const WebRtc_UWord32 rate) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000273 assert(payloadName);
pwestin@webrtc.org00741872012-01-19 15:56:10 +0000274 CriticalSectionScoped cs(_sendCritsect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000275
pwestin@webrtc.org00741872012-01-19 15:56:10 +0000276 std::map<WebRtc_Word8, ModuleRTPUtility::Payload*>::iterator it =
277 _payloadTypeMap.find(payloadNumber);
niklase@google.com470e71d2011-07-07 08:21:25 +0000278
pwestin@webrtc.org00741872012-01-19 15:56:10 +0000279 if (_payloadTypeMap.end() != it) {
280 // we already use this payload type
281 ModuleRTPUtility::Payload* payload = it->second;
282 assert(payload);
niklase@google.com470e71d2011-07-07 08:21:25 +0000283
pwestin@webrtc.org00741872012-01-19 15:56:10 +0000284 // check if it's the same as we already have
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000285 if (ModuleRTPUtility::StringCompare(payload->name, payloadName,
286 RTP_PAYLOAD_NAME_SIZE - 1)) {
pwestin@webrtc.org00741872012-01-19 15:56:10 +0000287 if (_audioConfigured && payload->audio &&
288 payload->typeSpecific.Audio.frequency == frequency &&
289 (payload->typeSpecific.Audio.rate == rate ||
290 payload->typeSpecific.Audio.rate == 0 || rate == 0)) {
291 payload->typeSpecific.Audio.rate = rate;
292 // Ensure that we update the rate if new or old is zero
niklase@google.com470e71d2011-07-07 08:21:25 +0000293 return 0;
pwestin@webrtc.org00741872012-01-19 15:56:10 +0000294 }
295 if(!_audioConfigured && !payload->audio) {
296 return 0;
297 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000298 }
299 return -1;
pwestin@webrtc.org00741872012-01-19 15:56:10 +0000300 }
301 WebRtc_Word32 retVal = -1;
302 ModuleRTPUtility::Payload* payload = NULL;
303 if (_audioConfigured) {
304 retVal = _audio->RegisterAudioPayload(payloadName, payloadNumber, frequency,
305 channels, rate, payload);
306 } else {
307 retVal = _video->RegisterVideoPayload(payloadName, payloadNumber, rate,
308 payload);
309 }
310 if(payload) {
311 _payloadTypeMap[payloadNumber] = payload;
312 }
313 return retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000314}
315
pwestin@webrtc.org00741872012-01-19 15:56:10 +0000316WebRtc_Word32 RTPSender::DeRegisterSendPayload(const WebRtc_Word8 payloadType) {
317 CriticalSectionScoped lock(_sendCritsect);
318
319 std::map<WebRtc_Word8, ModuleRTPUtility::Payload*>::iterator it =
320 _payloadTypeMap.find(payloadType);
321
322 if (_payloadTypeMap.end() == it) return -1;
323
324 ModuleRTPUtility::Payload* payload = it->second;
325 delete payload;
326 _payloadTypeMap.erase(it);
327 return 0;
328}
niklase@google.com470e71d2011-07-07 08:21:25 +0000329
330WebRtc_Word8 RTPSender::SendPayloadType() const
331{
332 return _payloadType;
333}
334
335
336int RTPSender::SendPayloadFrequency() const
337{
338 return _audio->AudioFrequency();
339}
340
341
niklase@google.com470e71d2011-07-07 08:21:25 +0000342WebRtc_Word32
343RTPSender::SetMaxPayloadLength(const WebRtc_UWord16 maxPayloadLength, const WebRtc_UWord16 packetOverHead)
344{
345 // sanity check
346 if(maxPayloadLength < 100 || maxPayloadLength > IP_PACKET_SIZE)
347 {
348 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
349 return -1;
350 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000351
352 CriticalSectionScoped cs(_sendCritsect);
353 _maxPayloadLength = maxPayloadLength;
354 _packetOverHead = packetOverHead;
355
356 WEBRTC_TRACE(kTraceInfo, kTraceRtpRtcp, _id, "SetMaxPayloadLength to %d.", maxPayloadLength);
357 return 0;
358}
359
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000360WebRtc_UWord16 RTPSender::MaxDataPayloadLength() const {
361 if(_audioConfigured) {
362 return _maxPayloadLength - RTPHeaderLength();
363 } else {
364 return _maxPayloadLength - RTPHeaderLength() -
365 _video->FECPacketOverhead() - ((_RTX) ? 2 : 0);
366 // Include the FEC/ULP/RED overhead.
367 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000368}
369
370WebRtc_UWord16
371RTPSender::MaxPayloadLength() const
372{
373 return _maxPayloadLength;
374}
375
376WebRtc_UWord16
377RTPSender::PacketOverHead() const
378{
379 return _packetOverHead;
380}
381
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000382void RTPSender::SetTransmissionSmoothingStatus(const bool enable) {
383 CriticalSectionScoped cs(_sendCritsect);
384 _transmissionSmoothing = enable;
385}
386
387bool RTPSender::TransmissionSmoothingStatus() const {
388 CriticalSectionScoped cs(_sendCritsect);
389 return _transmissionSmoothing;
390}
391
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000392void RTPSender::SetRTXStatus(const bool enable,
393 const bool setSSRC,
394 const WebRtc_UWord32 SSRC) {
395 CriticalSectionScoped cs(_sendCritsect);
396 _RTX = enable;
397 if (enable) {
398 if (setSSRC) {
399 _ssrcRTX = SSRC;
400 } else {
401 _ssrcRTX = _ssrcDB.CreateSSRC(); // can't be 0
402 }
403 }
404}
405
406void RTPSender::RTXStatus(bool* enable,
407 WebRtc_UWord32* SSRC) const {
408 CriticalSectionScoped cs(_sendCritsect);
409 *enable = _RTX;
410 *SSRC = _ssrcRTX;
411}
412
pwestin@webrtc.org00741872012-01-19 15:56:10 +0000413WebRtc_Word32 RTPSender::CheckPayloadType(const WebRtc_Word8 payloadType,
414 RtpVideoCodecTypes& videoType) {
415 CriticalSectionScoped cs(_sendCritsect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000416
pwestin@webrtc.org00741872012-01-19 15:56:10 +0000417 if (payloadType < 0) {
418 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
419 "\tinvalid payloadType (%d)", payloadType);
420 return -1;
421 }
422 if (_audioConfigured) {
423 WebRtc_Word8 redPlType = -1;
424 if (_audio->RED(redPlType) == 0) {
425 // We have configured RED.
426 if(redPlType == payloadType) {
427 // And it's a match...
428 return 0;
429 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000430 }
pwestin@webrtc.org00741872012-01-19 15:56:10 +0000431 }
432 if (_payloadType == payloadType) {
433 if (!_audioConfigured) {
434 videoType = _video->VideoCodecType();
niklase@google.com470e71d2011-07-07 08:21:25 +0000435 }
436 return 0;
pwestin@webrtc.org00741872012-01-19 15:56:10 +0000437 }
438 std::map<WebRtc_Word8, ModuleRTPUtility::Payload*>::iterator it =
439 _payloadTypeMap.find(payloadType);
440 if (it == _payloadTypeMap.end()) {
441 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
442 "\tpayloadType:%d not registered", payloadType);
443 return -1;
444 }
445 _payloadType = payloadType;
446 ModuleRTPUtility::Payload* payload = it->second;
447 assert(payload);
448 if (payload->audio) {
449 if (_audioConfigured) {
450 // Extract payload frequency
451 int payloadFreqHz;
452 if (ModuleRTPUtility::StringCompare(payload->name,"g722",4)&&
453 (payload->name[4] == 0)) {
454 //Check that strings end there, g722.1...
455 // Special case for G.722, bug in spec
456 payloadFreqHz=8000;
457 } else {
458 payloadFreqHz=payload->typeSpecific.Audio.frequency;
459 }
460
461 //we don't do anything if it's CN
462 if ((_audio->AudioFrequency() != payloadFreqHz)&&
463 (!ModuleRTPUtility::StringCompare(payload->name,"cn",2))) {
464 _audio->SetAudioFrequency(payloadFreqHz);
465 // We need to correct the timestamp again,
466 // since this might happen after we've set it
467 WebRtc_UWord32 RTPtime =
468 ModuleRTPUtility::GetCurrentRTP(&_clock, payloadFreqHz);
469 SetStartTimestamp(RTPtime);
470 // will be ignored if it's already configured via API
471 }
472 }
473 } else {
474 if(!_audioConfigured) {
475 _video->SetVideoCodecType(payload->typeSpecific.Video.videoCodecType);
476 videoType = payload->typeSpecific.Video.videoCodecType;
477 _video->SetMaxConfiguredBitrateVideo(
478 payload->typeSpecific.Video.maxRate);
479 }
480 }
481 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000482}
483
484WebRtc_Word32
485RTPSender::SendOutgoingData(const FrameType frameType,
486 const WebRtc_Word8 payloadType,
487 const WebRtc_UWord32 captureTimeStamp,
488 const WebRtc_UWord8* payloadData,
489 const WebRtc_UWord32 payloadSize,
490 const RTPFragmentationHeader* fragmentation,
491 VideoCodecInformation* codecInfo,
492 const RTPVideoTypeHeader* rtpTypeHdr)
493{
494 {
495 // Drop this packet if we're not sending media packets
496 CriticalSectionScoped cs(_sendCritsect);
497 if (!_sendingMedia)
498 {
499 return 0;
500 }
501 }
niklas.enbom@webrtc.org553657b2012-01-12 08:49:34 +0000502 RtpVideoCodecTypes videoType = kRtpNoVideo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000503 if(CheckPayloadType(payloadType, videoType) != 0)
504 {
505 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument failed to find payloadType:%d", __FUNCTION__, payloadType);
506 return -1;
507 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000508
509 if(_audioConfigured)
510 {
511 // assert video frameTypes
512 assert(frameType == kAudioFrameSpeech ||
513 frameType == kAudioFrameCN ||
514 frameType == kFrameEmpty);
515
516 return _audio->SendAudio(frameType, payloadType, captureTimeStamp, payloadData, payloadSize,fragmentation);
517 } else
518 {
pwestin@webrtc.orgddab60b2012-04-23 14:52:15 +0000519 // Assert on audio frameTypes.
520 assert(frameType != kAudioFrameSpeech &&
521 frameType != kAudioFrameCN);
niklase@google.com470e71d2011-07-07 08:21:25 +0000522
pwestin@webrtc.orgddab60b2012-04-23 14:52:15 +0000523 // If the encoder generate an empty frame send pading.
524 if (frameType == kFrameEmpty) {
525 // Current bitrate since last estimate(1 second) averaged with the
526 // estimate since then, to get the most up to date bitrate.
527 uint32_t current_bitrate = BitrateNow();
528 int bitrate_diff = _targetSendBitrate * 1000 - current_bitrate;
529 if (bitrate_diff > 0) {
530 int bytes = 0;
531 if (current_bitrate == 0) {
532 // Start up phase. Send one 33.3 ms batch to start with.
533 bytes = (bitrate_diff / 8) / 30;
534 } else {
535 bytes = (bitrate_diff / 8);
536 // Cap at 200 ms of target send data.
537 int bytes_cap = _targetSendBitrate * 25; // 1000 / 8 / 5
538 if (bytes_cap > bytes) {
539 bytes = bytes_cap;
540 }
541 }
542 // Send pading data.
543 return SendPadData(payloadType, captureTimeStamp, bytes);
544 }
545 return 0;
546 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000547 return _video->SendVideo(videoType,
548 frameType,
549 payloadType,
550 captureTimeStamp,
551 payloadData,
552 payloadSize,
553 fragmentation,
554 codecInfo,
555 rtpTypeHdr);
556 }
557}
558
pwestin@webrtc.org12d97f62012-01-05 10:54:44 +0000559WebRtc_Word32 RTPSender::SendPadData(WebRtc_Word8 payload_type,
560 WebRtc_UWord32 capture_timestamp,
561 WebRtc_Word32 bytes) {
562 // Drop this packet if we're not sending media packets
563 if (!_sendingMedia) {
564 return 0;
565 }
566 // Max in the RFC 3550 is 255 bytes, we limit it to be modulus 32 for SRTP.
567 int max_length = 224;
568 WebRtc_UWord8 data_buffer[IP_PACKET_SIZE];
569
570 for (; bytes > 0; bytes -= max_length) {
asapersson@webrtc.org63a34f42012-04-20 13:20:27 +0000571 int padding_bytes_in_packet = max_length;
572 if (bytes < max_length) {
573 padding_bytes_in_packet = (bytes + 16) & 0xffe0; // Keep our modulus 32.
574 }
575 if (padding_bytes_in_packet < 32) {
576 // Sanity don't send empty packets.
577 break;
578 }
579
pwestin@webrtc.org12d97f62012-01-05 10:54:44 +0000580 WebRtc_Word32 header_length;
581 {
582 // Correct seq num, timestamp and payload type.
583 header_length = BuildRTPheader(data_buffer,
584 payload_type,
585 false, // No markerbit.
586 capture_timestamp,
587 true, // Timestamp provided.
588 true); // Increment sequence number.
589 }
590 data_buffer[0] |= 0x20; // Set padding bit.
591 WebRtc_Word32* data =
592 reinterpret_cast<WebRtc_Word32*>(&(data_buffer[header_length]));
593
pwestin@webrtc.org12d97f62012-01-05 10:54:44 +0000594 // Fill data buffer with random data.
595 for(int j = 0; j < (padding_bytes_in_packet >> 2); j++) {
596 data[j] = rand();
597 }
598 // Set number of padding bytes in the last byte of the packet.
599 data_buffer[header_length + padding_bytes_in_packet - 1] =
600 padding_bytes_in_packet;
601 // Send the packet
602 if (0 > SendToNetwork(data_buffer,
603 padding_bytes_in_packet,
604 header_length,
605 kDontRetransmit)) {
606 // Error sending the packet.
607 break;
608 }
609 }
610 if (bytes > 31) { // 31 due to our modulus 32.
611 // We did not manage to send all bytes.
612 return -1;
613 }
614 return 0;
615}
616
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000617WebRtc_Word32 RTPSender::SetStorePacketsStatus(
618 const bool enable,
619 const WebRtc_UWord16 numberToStore) {
620 _packetHistory->SetStorePacketsStatus(enable, numberToStore);
621 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000622}
623
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000624bool RTPSender::StorePackets() const {
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000625 return _packetHistory->StorePackets();
niklase@google.com470e71d2011-07-07 08:21:25 +0000626}
627
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000628WebRtc_Word32 RTPSender::ReSendPacket(WebRtc_UWord16 packet_id,
629 WebRtc_UWord32 min_resend_time) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000630
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000631 WebRtc_UWord16 length = IP_PACKET_SIZE;
632 WebRtc_UWord8 data_buffer[IP_PACKET_SIZE];
633 WebRtc_UWord8* buffer_to_send_ptr = data_buffer;
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000634
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000635 WebRtc_UWord32 stored_time_in_ms;
636 StorageType type;
637 bool found = _packetHistory->GetRTPPacket(packet_id,
638 min_resend_time, data_buffer, &length, &stored_time_in_ms, &type);
639 if (!found) {
640 // Packet not found.
asapersson@webrtc.org83ed0a42012-04-23 12:43:05 +0000641 return 0;
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000642 }
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000643
644 if (length == 0 || type == kDontRetransmit) {
645 // No bytes copied (packet recently resent, skip resending) or
646 // packet should not be retransmitted.
647 return 0;
648 }
649
pwestin@webrtc.orgb30f0ed2012-01-23 16:23:31 +0000650 WebRtc_UWord8 data_buffer_rtx[IP_PACKET_SIZE];
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000651 if (_RTX) {
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000652 buffer_to_send_ptr = data_buffer_rtx;
653
654 CriticalSectionScoped cs(_sendCritsect);
655 // Add RTX header.
656 ModuleRTPUtility::RTPHeaderParser rtpParser(
657 reinterpret_cast<const WebRtc_UWord8*>(data_buffer),
658 length);
659
660 WebRtcRTPHeader rtp_header;
661 rtpParser.Parse(rtp_header);
662
663 // Add original RTP header.
664 memcpy(data_buffer_rtx, data_buffer, rtp_header.header.headerLength);
665
666 // Replace sequence number.
667 WebRtc_UWord8* ptr = data_buffer_rtx + 2;
668 ModuleRTPUtility::AssignUWord16ToBuffer(ptr, _sequenceNumberRTX++);
669
670 // Replace SSRC.
671 ptr += 6;
672 ModuleRTPUtility::AssignUWord32ToBuffer(ptr, _ssrcRTX);
673
674 // Add OSN (original sequence number).
675 ptr = data_buffer_rtx + rtp_header.header.headerLength;
676 ModuleRTPUtility::AssignUWord16ToBuffer(
677 ptr, rtp_header.header.sequenceNumber);
678 ptr += 2;
679
680 // Add original payload data.
681 memcpy(ptr,
682 data_buffer + rtp_header.header.headerLength,
683 length - rtp_header.header.headerLength);
684 length += 2;
685 }
686
687 WebRtc_Word32 bytes_sent = ReSendToNetwork(buffer_to_send_ptr, length);
688 if (bytes_sent <= 0) {
689 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
690 "Transport failed to resend packet_id %u", packet_id);
691 return -1;
692 }
693
694 // Store the time when the packet was last resent.
695 _packetHistory->UpdateResendTime(packet_id);
696
697 return bytes_sent;
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000698}
699
700WebRtc_Word32 RTPSender::ReSendToNetwork(const WebRtc_UWord8* packet,
701 const WebRtc_UWord32 size) {
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000702 WebRtc_Word32 bytes_sent = -1;
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000703 {
704 CriticalSectionScoped lock(_transportCritsect);
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000705 if (_transport) {
706 bytes_sent = _transport->SendPacket(_id, packet, size);
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000707 }
708 }
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000709
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000710 if (bytes_sent <= 0) {
711 return -1;
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000712 }
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000713
714 // Update send statistics
715 CriticalSectionScoped cs(_sendCritsect);
716 Bitrate::Update(bytes_sent);
717 _packetsSent++;
718 // We on purpose don't add to _payloadBytesSent since this is a
719 // re-transmit and not new payload data.
720 return bytes_sent;
niklase@google.com470e71d2011-07-07 08:21:25 +0000721}
722
stefan@webrtc.org6a4bef42011-12-22 12:52:41 +0000723int RTPSender::SelectiveRetransmissions() const {
724 if (!_video) return -1;
725 return _video->SelectiveRetransmissions();
726}
727
728int RTPSender::SetSelectiveRetransmissions(uint8_t settings) {
729 if (!_video) return -1;
730 return _video->SetSelectiveRetransmissions(settings);
731}
732
niklase@google.com470e71d2011-07-07 08:21:25 +0000733void
734RTPSender::OnReceivedNACK(const WebRtc_UWord16 nackSequenceNumbersLength,
735 const WebRtc_UWord16* nackSequenceNumbers,
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000736 const WebRtc_UWord16 avgRTT) {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000737 const WebRtc_UWord32 now = _clock.GetTimeInMS();
niklase@google.com470e71d2011-07-07 08:21:25 +0000738 WebRtc_UWord32 bytesReSent = 0;
739
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000740 // Enough bandwidth to send NACK?
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000741 if (!ProcessNACKBitRate(now)) {
742 WEBRTC_TRACE(kTraceStream,
743 kTraceRtpRtcp,
744 _id,
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000745 "NACK bitrate reached. Skip sending NACK response. Target %d",
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000746 TargetSendBitrateKbit());
747 return;
748 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000749
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000750 for (WebRtc_UWord16 i = 0; i < nackSequenceNumbersLength; ++i) {
751 const WebRtc_Word32 bytesSent = ReSendPacket(nackSequenceNumbers[i],
752 5+avgRTT);
753 if (bytesSent > 0) {
754 bytesReSent += bytesSent;
755 } else if (bytesSent == 0) {
756 // The packet has previously been resent.
757 // Try resending next packet in the list.
758 continue;
759 } else if (bytesSent < 0) {
760 // Failed to send one Sequence number. Give up the rest in this nack.
761 WEBRTC_TRACE(kTraceWarning,
762 kTraceRtpRtcp,
763 _id,
764 "Failed resending RTP packet %d, Discard rest of packets",
765 nackSequenceNumbers[i]);
766 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000767 }
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000768 // delay bandwidth estimate (RTT * BW)
769 if (TargetSendBitrateKbit() != 0 && avgRTT) {
770 // kbits/s * ms = bits => bits/8 = bytes
771 WebRtc_UWord32 targetBytes =
772 (static_cast<WebRtc_UWord32>(TargetSendBitrateKbit()) * avgRTT) >> 3;
773 if (bytesReSent > targetBytes) {
774 break; // ignore the rest of the packets in the list
775 }
776 }
777 }
778 if (bytesReSent > 0) {
779 // TODO(pwestin) consolidate these two methods.
780 UpdateNACKBitRate(bytesReSent, now);
781 _nackBitrate.Update(bytesReSent);
782 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000783}
784
785/**
786* @return true if the nack bitrate is lower than the requested max bitrate
787*/
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000788bool RTPSender::ProcessNACKBitRate(const WebRtc_UWord32 now) {
789 WebRtc_UWord32 num = 0;
790 WebRtc_Word32 byteCount = 0;
791 const WebRtc_UWord32 avgInterval=1000;
niklase@google.com470e71d2011-07-07 08:21:25 +0000792
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000793 CriticalSectionScoped cs(_sendCritsect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000794
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000795 if (_targetSendBitrate == 0) {
796 return true;
797 }
798 for (num = 0; num < NACK_BYTECOUNT_SIZE; num++) {
799 if ((now - _nackByteCountTimes[num]) > avgInterval) {
800 // don't use data older than 1sec
801 break;
802 } else {
803 byteCount += _nackByteCount[num];
niklase@google.com470e71d2011-07-07 08:21:25 +0000804 }
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000805 }
806 WebRtc_Word32 timeInterval = avgInterval;
807 if (num == NACK_BYTECOUNT_SIZE) {
808 // More than NACK_BYTECOUNT_SIZE nack messages has been received
809 // during the last msgInterval
810 timeInterval = now - _nackByteCountTimes[num-1];
811 if(timeInterval < 0) {
812 timeInterval = avgInterval;
niklase@google.com470e71d2011-07-07 08:21:25 +0000813 }
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000814 }
815 return (byteCount*8) < (_targetSendBitrate * timeInterval);
niklase@google.com470e71d2011-07-07 08:21:25 +0000816}
817
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000818void RTPSender::UpdateNACKBitRate(const WebRtc_UWord32 bytes,
819 const WebRtc_UWord32 now) {
820 CriticalSectionScoped cs(_sendCritsect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000821
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000822 // save bitrate statistics
823 if(bytes > 0) {
824 if(now == 0) {
825 // add padding length
826 _nackByteCount[0] += bytes;
827 } else {
828 if(_nackByteCountTimes[0] == 0) {
829 // first no shift
830 } else {
831 // shift
832 for(int i = (NACK_BYTECOUNT_SIZE-2); i >= 0 ; i--) {
833 _nackByteCount[i+1] = _nackByteCount[i];
834 _nackByteCountTimes[i+1] = _nackByteCountTimes[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000835 }
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000836 }
837 _nackByteCount[0] = bytes;
838 _nackByteCountTimes[0] = now;
niklase@google.com470e71d2011-07-07 08:21:25 +0000839 }
pwestin@webrtc.org8281e7d2012-01-10 14:09:18 +0000840 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000841}
842
pwestin@webrtc.orgddab60b2012-04-23 14:52:15 +0000843// Function triggered by timer.
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000844void RTPSender::ProcessSendToNetwork() {
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000845 WebRtc_UWord32 delta_time_ms;
846 {
847 CriticalSectionScoped cs(_sendCritsect);
848
849 if (!_transmissionSmoothing) {
850 return;
851 }
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000852 WebRtc_UWord32 now = _clock.GetTimeInMS();
853 delta_time_ms = now - _timeLastSendToNetworkUpdate;
854 _timeLastSendToNetworkUpdate = now;
855 }
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000856 _sendBucket.UpdateBytesPerInterval(delta_time_ms, _targetSendBitrate);
857
858 while (!_sendBucket.Empty()) {
859
860 WebRtc_Word32 seq_num = _sendBucket.GetNextPacket();
861 if (seq_num < 0) {
862 break;
863 }
864
865 WebRtc_UWord8 data_buffer[IP_PACKET_SIZE];
866 WebRtc_UWord16 length = IP_PACKET_SIZE;
867 WebRtc_UWord32 stored_time_ms;
868 StorageType type;
asapersson@webrtc.org869ce2d2012-01-16 11:58:36 +0000869 bool found = _packetHistory->GetRTPPacket(seq_num, 0, data_buffer, &length,
870 &stored_time_ms, &type);
871 if (!found) {
872 assert(false);
873 return;
874 }
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000875 assert(length > 0);
876
877 WebRtc_UWord32 diff_ms = _clock.GetTimeInMS() - stored_time_ms;
878
879 ModuleRTPUtility::RTPHeaderParser rtpParser(data_buffer, length);
880 WebRtcRTPHeader rtp_header;
asapersson@webrtc.org869ce2d2012-01-16 11:58:36 +0000881 rtpParser.Parse(rtp_header);
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000882
883 UpdateTransmissionTimeOffset(data_buffer, length, rtp_header, diff_ms);
884
885 // Send packet
886 WebRtc_Word32 bytes_sent = -1;
887 {
888 CriticalSectionScoped cs(_transportCritsect);
889 if (_transport) {
890 bytes_sent = _transport->SendPacket(_id, data_buffer, length);
891 }
892 }
893
894 // Update send statistics
895 if (bytes_sent > 0) {
896 CriticalSectionScoped cs(_sendCritsect);
897 Bitrate::Update(bytes_sent);
898 _packetsSent++;
899 if (bytes_sent > rtp_header.header.headerLength) {
900 _payloadBytesSent += bytes_sent - rtp_header.header.headerLength;
901 }
902 }
903 }
904}
905
niklase@google.com470e71d2011-07-07 08:21:25 +0000906WebRtc_Word32
907RTPSender::SendToNetwork(const WebRtc_UWord8* buffer,
908 const WebRtc_UWord16 length,
909 const WebRtc_UWord16 rtpLength,
stefan@webrtc.org6a4bef42011-12-22 12:52:41 +0000910 const StorageType storage)
niklase@google.com470e71d2011-07-07 08:21:25 +0000911{
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000912 // Used for NACK or to spead out the transmission of packets.
913 if (_packetHistory->PutRTPPacket(
914 buffer, rtpLength + length, _maxPayloadLength, storage) != 0) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000915 return -1;
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000916 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000917
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000918 if (_transmissionSmoothing) {
919 const WebRtc_UWord16 sequenceNumber = (buffer[2] << 8) + buffer[3];
920 _sendBucket.Fill(sequenceNumber, rtpLength + length);
921 // Packet will be sent at a later time.
922 return 0;
923 }
stefan@webrtc.org6a4bef42011-12-22 12:52:41 +0000924
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000925 // Send packet
926 WebRtc_Word32 bytes_sent = -1;
927 {
928 CriticalSectionScoped cs(_transportCritsect);
929 if (_transport) {
930 bytes_sent = _transport->SendPacket(_id, buffer, length + rtpLength);
stefan@webrtc.org6a4bef42011-12-22 12:52:41 +0000931 }
932 }
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +0000933
934 if (bytes_sent <= 0) {
935 return -1;
936 }
937
938 // Update send statistics
939 CriticalSectionScoped cs(_sendCritsect);
940 Bitrate::Update(bytes_sent);
941 _packetsSent++;
942 if (bytes_sent > rtpLength) {
943 _payloadBytesSent += bytes_sent - rtpLength;
944 }
945 return 0;
stefan@webrtc.org6a4bef42011-12-22 12:52:41 +0000946}
947
niklase@google.com470e71d2011-07-07 08:21:25 +0000948void
949RTPSender::ProcessBitrate()
950{
951 CriticalSectionScoped cs(_sendCritsect);
952
953 Bitrate::Process();
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +0000954 _nackBitrate.Process();
wu@webrtc.org76aea652011-10-17 21:40:32 +0000955
956 if (_audioConfigured)
957 return;
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +0000958 _video->ProcessBitrate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000959}
960
961WebRtc_UWord16
962RTPSender::RTPHeaderLength() const
963{
964 WebRtc_UWord16 rtpHeaderLength = 12;
965
966 if(_includeCSRCs)
967 {
968 rtpHeaderLength += sizeof(WebRtc_UWord32)*_CSRCs;
969 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000970 rtpHeaderLength += RtpHeaderExtensionTotalLength();
971
niklase@google.com470e71d2011-07-07 08:21:25 +0000972 return rtpHeaderLength;
973}
974
975WebRtc_UWord16
976RTPSender::IncrementSequenceNumber()
977{
978 CriticalSectionScoped cs(_sendCritsect);
979 return _sequenceNumber++;
980}
981
982WebRtc_Word32
983RTPSender::ResetDataCounters()
984{
985 _packetsSent = 0;
986 _payloadBytesSent = 0;
987
988 return 0;
989}
990
991// number of sent RTP packets
992// dont use critsect to avoid potental deadlock
993WebRtc_UWord32
994RTPSender::Packets() const
995{
996 return _packetsSent;
997}
998
999// number of sent RTP bytes
1000// dont use critsect to avoid potental deadlock
1001WebRtc_UWord32
1002RTPSender::Bytes() const
1003{
1004 return _payloadBytesSent;
1005}
1006
1007WebRtc_Word32
1008RTPSender::BuildRTPheader(WebRtc_UWord8* dataBuffer,
1009 const WebRtc_Word8 payloadType,
1010 const bool markerBit,
1011 const WebRtc_UWord32 captureTimeStamp,
1012 const bool timeStampProvided,
1013 const bool incSequenceNumber)
1014{
1015 assert(payloadType>=0);
1016
1017 CriticalSectionScoped cs(_sendCritsect);
1018
1019 dataBuffer[0] = static_cast<WebRtc_UWord8>(0x80); // version 2
1020 dataBuffer[1] = static_cast<WebRtc_UWord8>(payloadType);
1021 if (markerBit)
1022 {
1023 dataBuffer[1] |= kRtpMarkerBitMask; // MarkerBit is set
1024 }
1025
1026 if(timeStampProvided)
1027 {
1028 _timeStamp = _startTimeStamp + captureTimeStamp;
1029 } else
1030 {
1031 // make a unique time stamp
1032 // used for inband signaling
1033 // we can't inc by the actual time, since then we increase the risk of back timing
1034 _timeStamp++;
1035 }
1036
1037 ModuleRTPUtility::AssignUWord16ToBuffer(dataBuffer+2, _sequenceNumber);
1038 ModuleRTPUtility::AssignUWord32ToBuffer(dataBuffer+4, _timeStamp);
1039 ModuleRTPUtility::AssignUWord32ToBuffer(dataBuffer+8, _ssrc);
1040
1041 WebRtc_Word32 rtpHeaderLength = 12;
1042
1043 // Add the CSRCs if any
1044 if (_includeCSRCs && _CSRCs > 0)
1045 {
1046 if(_CSRCs > kRtpCsrcSize)
1047 {
1048 // error
1049 assert(false);
1050 return -1;
1051 }
1052 WebRtc_UWord8* ptr = &dataBuffer[rtpHeaderLength];
1053 for (WebRtc_UWord32 i = 0; i < _CSRCs; ++i)
1054 {
1055 ModuleRTPUtility::AssignUWord32ToBuffer(ptr, _CSRC[i]);
1056 ptr +=4;
1057 }
1058 dataBuffer[0] = (dataBuffer[0]&0xf0) | _CSRCs;
1059
1060 // Update length of header
1061 rtpHeaderLength += sizeof(WebRtc_UWord32)*_CSRCs;
1062 }
1063 {
1064 _sequenceNumber++; // prepare for next packet
1065 }
1066
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001067 WebRtc_UWord16 len = BuildRTPHeaderExtension(dataBuffer + rtpHeaderLength);
1068 if (len)
1069 {
1070 dataBuffer[0] |= 0x10; // set eXtension bit
1071 rtpHeaderLength += len;
1072 }
1073
niklase@google.com470e71d2011-07-07 08:21:25 +00001074 return rtpHeaderLength;
1075}
1076
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001077WebRtc_UWord16
1078RTPSender::BuildRTPHeaderExtension(WebRtc_UWord8* dataBuffer) const
1079{
1080 if (_rtpHeaderExtensionMap.Size() <= 0) {
1081 return 0;
1082 }
1083
1084 /* RTP header extension, RFC 3550.
1085 0 1 2 3
1086 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
1087 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1088 | defined by profile | length |
1089 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1090 | header extension |
1091 | .... |
1092 */
1093
1094 const WebRtc_UWord32 kPosLength = 2;
1095 const WebRtc_UWord32 kHeaderLength = RTP_ONE_BYTE_HEADER_LENGTH_IN_BYTES;
1096
1097 // Add extension ID (0xBEDE).
1098 ModuleRTPUtility::AssignUWord16ToBuffer(dataBuffer,
1099 RTP_ONE_BYTE_HEADER_EXTENSION);
1100
1101 // Add extensions.
1102 WebRtc_UWord16 total_block_length = 0;
1103
1104 RTPExtensionType type = _rtpHeaderExtensionMap.First();
pwestin@webrtc.org6c1d4152012-01-04 17:04:51 +00001105 while (type != kRtpExtensionNone)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001106 {
1107 WebRtc_UWord8 block_length = 0;
pwestin@webrtc.org6c1d4152012-01-04 17:04:51 +00001108 if (type == kRtpExtensionTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001109 {
1110 block_length = BuildTransmissionTimeOffsetExtension(
1111 dataBuffer + kHeaderLength + total_block_length);
1112 }
1113 total_block_length += block_length;
1114 type = _rtpHeaderExtensionMap.Next(type);
1115 }
1116
1117 if (total_block_length == 0)
1118 {
1119 // No extension added.
1120 return 0;
1121 }
1122
1123 // Set header length (in number of Word32, header excluded).
1124 assert(total_block_length % 4 == 0);
1125 ModuleRTPUtility::AssignUWord16ToBuffer(dataBuffer + kPosLength,
1126 total_block_length / 4);
1127
1128 // Total added length.
1129 return kHeaderLength + total_block_length;
1130}
1131
1132WebRtc_UWord8
1133RTPSender::BuildTransmissionTimeOffsetExtension(WebRtc_UWord8* dataBuffer) const
1134{
1135 // From RFC 5450: Transmission Time Offsets in RTP Streams.
1136 //
1137 // The transmission time is signaled to the receiver in-band using the
1138 // general mechanism for RTP header extensions [RFC5285]. The payload
1139 // of this extension (the transmitted value) is a 24-bit signed integer.
1140 // When added to the RTP timestamp of the packet, it represents the
1141 // "effective" RTP transmission time of the packet, on the RTP
1142 // timescale.
1143 //
1144 // The form of the transmission offset extension block:
1145 //
1146 // 0 1 2 3
1147 // 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
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +00001148 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001149 // | ID | len=2 | transmission offset |
1150 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1151
1152 // Get id defined by user.
1153 WebRtc_UWord8 id;
pwestin@webrtc.org6c1d4152012-01-04 17:04:51 +00001154 if (_rtpHeaderExtensionMap.GetId(kRtpExtensionTransmissionTimeOffset, &id)
1155 != 0) {
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001156 // Not registered.
1157 return 0;
1158 }
1159
1160 int pos = 0;
1161 const WebRtc_UWord8 len = 2;
1162 dataBuffer[pos++] = (id << 4) + len;
1163 ModuleRTPUtility::AssignUWord24ToBuffer(dataBuffer + pos,
1164 _transmissionTimeOffset);
1165 pos += 3;
1166 assert(pos == TRANSMISSION_TIME_OFFSET_LENGTH_IN_BYTES);
1167 return TRANSMISSION_TIME_OFFSET_LENGTH_IN_BYTES;
1168}
1169
asapersson@webrtc.org0b3c35a2012-01-16 11:06:31 +00001170void RTPSender::UpdateTransmissionTimeOffset(
1171 WebRtc_UWord8* rtp_packet,
1172 const WebRtc_UWord16 rtp_packet_length,
1173 const WebRtcRTPHeader& rtp_header,
1174 const WebRtc_UWord32 time_ms) const {
1175 CriticalSectionScoped cs(_sendCritsect);
1176
1177 // Get length until start of transmission block.
1178 int transmission_block_pos =
1179 _rtpHeaderExtensionMap.GetLengthUntilBlockStartInBytes(
1180 kRtpExtensionTransmissionTimeOffset);
1181 if (transmission_block_pos < 0) {
1182 WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id,
1183 "Failed to update transmission time offset, not registered.");
1184 return;
1185 }
1186
1187 int block_pos = 12 + rtp_header.header.numCSRCs + transmission_block_pos;
1188 if ((rtp_packet_length < block_pos + 4)) {
1189 WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id,
1190 "Failed to update transmission time offset, invalid length.");
1191 return;
1192 }
1193
1194 // Verify that header contains extension.
1195 if (!((rtp_packet[12 + rtp_header.header.numCSRCs] == 0xBE) &&
1196 (rtp_packet[12 + rtp_header.header.numCSRCs + 1] == 0xDE))) {
1197 WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id,
1198 "Failed to update transmission time offset, hdr extension not found.");
1199 return;
1200 }
1201
1202 // Get id.
1203 WebRtc_UWord8 id = 0;
1204 if (_rtpHeaderExtensionMap.GetId(kRtpExtensionTransmissionTimeOffset,
1205 &id) != 0) {
1206 WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id,
1207 "Failed to update transmission time offset, no id.");
1208 return;
1209 }
1210
1211 // Verify first byte in block.
1212 const WebRtc_UWord8 first_block_byte = (id << 4) + 2;
1213 if (rtp_packet[block_pos] != first_block_byte) {
1214 WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id,
1215 "Failed to update transmission time offset.");
1216 return;
1217 }
1218
1219 // Update transmission offset field.
1220 ModuleRTPUtility::AssignUWord24ToBuffer(rtp_packet + block_pos + 1,
1221 time_ms * 90); // RTP timestamp
1222}
1223
niklase@google.com470e71d2011-07-07 08:21:25 +00001224WebRtc_Word32
1225RTPSender::RegisterSendTransport(Transport* transport)
1226{
1227 CriticalSectionScoped cs(_transportCritsect);
1228 _transport = transport;
1229 return 0;
1230}
1231
1232void
1233RTPSender::SetSendingStatus(const bool enabled)
1234{
1235 if(enabled)
1236 {
1237 WebRtc_UWord32 freq;
1238 if(_audioConfigured)
1239 {
1240 WebRtc_UWord32 frequency = _audio->AudioFrequency();
1241
1242 // sanity
1243 switch(frequency)
1244 {
1245 case 8000:
1246 case 12000:
1247 case 16000:
1248 case 24000:
1249 case 32000:
1250 break;
1251 default:
1252 assert(false);
1253 return;
1254 }
1255 freq = frequency;
1256 } else
1257 {
1258 freq = 90000; // 90 KHz for all video
1259 }
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001260 WebRtc_UWord32 RTPtime = ModuleRTPUtility::GetCurrentRTP(&_clock, freq);
niklase@google.com470e71d2011-07-07 08:21:25 +00001261
1262 SetStartTimestamp(RTPtime); // will be ignored if it's already configured via API
1263
1264 } else
1265 {
1266 if(!_ssrcForced)
1267 {
1268 // generate a new SSRC
1269 _ssrcDB.ReturnSSRC(_ssrc);
1270 _ssrc = _ssrcDB.CreateSSRC(); // can't be 0
1271
1272 }
1273 if(!_sequenceNumberForced && !_ssrcForced) // don't initialize seq number if SSRC passed externally
1274 {
1275 // generate a new sequence number
1276 _sequenceNumber = rand() / (RAND_MAX / MAX_INIT_RTP_SEQ_NUMBER);
1277 }
1278 }
1279}
1280
1281void
1282RTPSender::SetSendingMediaStatus(const bool enabled)
1283{
1284 CriticalSectionScoped cs(_sendCritsect);
1285 _sendingMedia = enabled;
1286}
1287
1288bool
1289RTPSender::SendingMedia() const
1290{
1291 CriticalSectionScoped cs(_sendCritsect);
1292 return _sendingMedia;
1293}
1294
1295WebRtc_UWord32
1296RTPSender::Timestamp() const
1297{
1298 CriticalSectionScoped cs(_sendCritsect);
1299 return _timeStamp;
1300}
1301
1302
1303WebRtc_Word32
1304RTPSender::SetStartTimestamp( const WebRtc_UWord32 timestamp, const bool force)
1305{
1306 CriticalSectionScoped cs(_sendCritsect);
1307 if(force)
1308 {
1309 _startTimeStampForced = force;
1310 _startTimeStamp = timestamp;
1311 } else
1312 {
1313 if(!_startTimeStampForced)
1314 {
1315 _startTimeStamp = timestamp;
1316 }
1317 }
1318 return 0;
1319}
1320
1321WebRtc_UWord32
1322RTPSender::StartTimestamp() const
1323{
1324 CriticalSectionScoped cs(_sendCritsect);
1325 return _startTimeStamp;
1326}
1327
1328WebRtc_UWord32
1329RTPSender::GenerateNewSSRC()
1330{
1331 // if configured via API, return 0
1332 CriticalSectionScoped cs(_sendCritsect);
1333
1334 if(_ssrcForced)
1335 {
1336 return 0;
1337 }
1338 _ssrc = _ssrcDB.CreateSSRC(); // can't be 0
1339 return _ssrc;
1340}
1341
1342WebRtc_Word32
1343RTPSender::SetSSRC(WebRtc_UWord32 ssrc)
1344{
1345 // this is configured via the API
1346 CriticalSectionScoped cs(_sendCritsect);
1347
1348 if (_ssrc == ssrc && _ssrcForced)
1349 {
1350 return 0; // since it's same ssrc, don't reset anything
1351 }
1352
1353 _ssrcForced = true;
1354
1355 _ssrcDB.ReturnSSRC(_ssrc);
1356 _ssrcDB.RegisterSSRC(ssrc);
1357 _ssrc = ssrc;
1358
1359 if(!_sequenceNumberForced)
1360 {
1361 _sequenceNumber = rand() / (RAND_MAX / MAX_INIT_RTP_SEQ_NUMBER);
1362 }
1363 return 0;
1364}
1365
1366WebRtc_UWord32
1367RTPSender::SSRC() const
1368{
1369 CriticalSectionScoped cs(_sendCritsect);
1370 return _ssrc;
1371}
1372
1373WebRtc_Word32
1374RTPSender::SetCSRCStatus(const bool include)
1375{
1376 _includeCSRCs = include;
1377 return 0;
1378}
1379
1380WebRtc_Word32
1381RTPSender::SetCSRCs(const WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize],
1382 const WebRtc_UWord8 arrLength)
1383{
1384 if(arrLength > kRtpCsrcSize)
1385 {
1386 assert(false);
1387 return -1;
1388 }
1389
1390 CriticalSectionScoped cs(_sendCritsect);
1391
1392 for(int i = 0; i < arrLength;i++)
1393 {
1394 _CSRC[i] = arrOfCSRC[i];
1395 }
1396 _CSRCs = arrLength;
1397 return 0;
1398}
1399
1400WebRtc_Word32
1401RTPSender::CSRCs(WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize]) const
1402{
1403 CriticalSectionScoped cs(_sendCritsect);
1404
1405 if(arrOfCSRC == NULL)
1406 {
1407 assert(false);
1408 return -1;
1409 }
1410 for(int i = 0; i < _CSRCs && i < kRtpCsrcSize;i++)
1411 {
1412 arrOfCSRC[i] = _CSRC[i];
1413 }
1414 return _CSRCs;
1415}
1416
1417WebRtc_Word32
1418RTPSender::SetSequenceNumber(WebRtc_UWord16 seq)
1419{
1420 CriticalSectionScoped cs(_sendCritsect);
1421 _sequenceNumberForced = true;
1422 _sequenceNumber = seq;
1423 return 0;
1424}
1425
1426WebRtc_UWord16
1427RTPSender::SequenceNumber() const
1428{
1429 CriticalSectionScoped cs(_sendCritsect);
1430 return _sequenceNumber;
1431}
1432
1433
1434 /*
1435 * Audio
1436 */
1437WebRtc_Word32
1438RTPSender::RegisterAudioCallback(RtpAudioFeedback* messagesCallback)
1439{
1440 if(!_audioConfigured)
1441 {
1442 return -1;
1443 }
1444 return _audio->RegisterAudioCallback(messagesCallback);
1445}
1446
1447 // Send a DTMF tone, RFC 2833 (4733)
1448WebRtc_Word32
1449RTPSender::SendTelephoneEvent(const WebRtc_UWord8 key,
1450 const WebRtc_UWord16 time_ms,
1451 const WebRtc_UWord8 level)
1452{
1453 if(!_audioConfigured)
1454 {
1455 return -1;
1456 }
1457 return _audio->SendTelephoneEvent(key, time_ms, level);
1458}
1459
1460bool
1461RTPSender::SendTelephoneEventActive(WebRtc_Word8& telephoneEvent) const
1462{
1463 if(!_audioConfigured)
1464 {
1465 return false;
1466 }
1467 return _audio->SendTelephoneEventActive(telephoneEvent);
1468}
1469
1470 // set audio packet size, used to determine when it's time to send a DTMF packet in silence (CNG)
1471WebRtc_Word32
1472RTPSender::SetAudioPacketSize(const WebRtc_UWord16 packetSizeSamples)
1473{
1474 if(!_audioConfigured)
1475 {
1476 return -1;
1477 }
1478 return _audio->SetAudioPacketSize(packetSizeSamples);
1479}
1480
1481WebRtc_Word32
1482RTPSender::SetAudioLevelIndicationStatus(const bool enable,
1483 const WebRtc_UWord8 ID)
1484{
1485 if(!_audioConfigured)
1486 {
1487 return -1;
1488 }
1489 return _audio->SetAudioLevelIndicationStatus(enable, ID);
1490}
1491
1492WebRtc_Word32
1493RTPSender::AudioLevelIndicationStatus(bool& enable,
1494 WebRtc_UWord8& ID) const
1495{
1496 return _audio->AudioLevelIndicationStatus(enable, ID);
1497}
1498
1499WebRtc_Word32
1500RTPSender::SetAudioLevel(const WebRtc_UWord8 level_dBov)
1501{
1502 return _audio->SetAudioLevel(level_dBov);
1503}
1504
1505 // Set payload type for Redundant Audio Data RFC 2198
1506WebRtc_Word32
1507RTPSender::SetRED(const WebRtc_Word8 payloadType)
1508{
1509 if(!_audioConfigured)
1510 {
1511 return -1;
1512 }
1513 return _audio->SetRED(payloadType);
1514}
1515
1516 // Get payload type for Redundant Audio Data RFC 2198
1517WebRtc_Word32
1518RTPSender::RED(WebRtc_Word8& payloadType) const
1519{
1520 if(!_audioConfigured)
1521 {
andrew@webrtc.org4f390002011-08-24 20:35:35 +00001522 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001523 }
1524 return _audio->RED(payloadType);
1525}
1526
1527 /*
1528 * Video
1529 */
1530VideoCodecInformation*
1531RTPSender::CodecInformationVideo()
1532{
1533 if(_audioConfigured)
1534 {
1535 return NULL;
1536 }
1537 return _video->CodecInformationVideo();
1538}
1539
1540RtpVideoCodecTypes
1541RTPSender::VideoCodecType() const
1542{
1543 if(_audioConfigured)
1544 {
1545 return kRtpNoVideo;
1546 }
1547 return _video->VideoCodecType();
1548}
1549
1550WebRtc_UWord32
1551RTPSender::MaxConfiguredBitrateVideo() const
1552{
1553 if(_audioConfigured)
1554 {
1555 return 0;
1556 }
1557 return _video->MaxConfiguredBitrateVideo();
1558}
1559
1560WebRtc_Word32
1561RTPSender::SendRTPIntraRequest()
1562{
1563 if(_audioConfigured)
1564 {
1565 return -1;
1566 }
1567 return _video->SendRTPIntraRequest();
1568}
1569
1570// FEC
1571WebRtc_Word32
1572RTPSender::SetGenericFECStatus(const bool enable,
1573 const WebRtc_UWord8 payloadTypeRED,
1574 const WebRtc_UWord8 payloadTypeFEC)
1575{
1576 if(_audioConfigured)
1577 {
1578 return -1;
1579 }
1580 return _video->SetGenericFECStatus(enable, payloadTypeRED, payloadTypeFEC);
1581}
1582
1583WebRtc_Word32
1584RTPSender::GenericFECStatus(bool& enable,
1585 WebRtc_UWord8& payloadTypeRED,
1586 WebRtc_UWord8& payloadTypeFEC) const
1587{
1588 if(_audioConfigured)
1589 {
1590 return -1;
1591 }
1592 return _video->GenericFECStatus(enable, payloadTypeRED, payloadTypeFEC);
1593}
1594
stefan@webrtc.orge0d6fa42012-03-20 22:10:56 +00001595WebRtc_Word32 RTPSender::SetFecParameters(
1596 const FecProtectionParams* delta_params,
1597 const FecProtectionParams* key_params) {
1598 if (_audioConfigured) {
1599 return -1;
1600 }
1601 return _video->SetFecParameters(delta_params, key_params);
marpan@google.com80c5d7a2011-07-15 21:32:40 +00001602}
niklase@google.com470e71d2011-07-07 08:21:25 +00001603} // namespace webrtc