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/video_engine/test/libvietest/include/tb_external_transport.h"
12
13 #include <assert.h>
14
15 #include <math.h>
16 #include <stdio.h> // printf
17 #include <stdlib.h> // rand
18
19 #if defined(WEBRTC_LINUX) || defined(__linux__)
20 #include <string.h>
21 #endif
22 #if defined(WEBRTC_MAC)
23 #include <string.h>
24 #endif
25
26 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
27 #include "webrtc/system_wrappers/interface/event_wrapper.h"
28 #include "webrtc/system_wrappers/interface/thread_wrapper.h"
29 #include "webrtc/system_wrappers/interface/tick_util.h"
30 #include "webrtc/video_engine/include/vie_network.h"
31
32 #if defined(_WIN32)
33 #pragma warning(disable: 4355) // 'this' : used in base member initializer list
34 #endif
35
36 const uint8_t kSenderReportPayloadType = 200;
37 const uint8_t kReceiverReportPayloadType = 201;
38
TbExternalTransport(webrtc::ViENetwork & vieNetwork,int sender_channel,TbExternalTransport::SsrcChannelMap * receive_channels)39 TbExternalTransport::TbExternalTransport(
40 webrtc::ViENetwork& vieNetwork,
41 int sender_channel,
42 TbExternalTransport::SsrcChannelMap* receive_channels)
43 :
44 sender_channel_(sender_channel),
45 receive_channels_(receive_channels),
46 _vieNetwork(vieNetwork),
47 _thread(*webrtc::ThreadWrapper::CreateThread(
48 ViEExternalTransportRun, this, webrtc::kHighPriority,
49 "AutotestTransport")),
50 _event(*webrtc::EventWrapper::Create()),
51 _crit(*webrtc::CriticalSectionWrapper::CreateCriticalSection()),
52 _statCrit(*webrtc::CriticalSectionWrapper::CreateCriticalSection()),
53 network_parameters_(),
54 _rtpCount(0),
55 _rtcpCount(0),
56 _dropCount(0),
57 packet_counters_(),
58 _rtpPackets(),
59 _rtcpPackets(),
60 _send_frame_callback(NULL),
61 _receive_frame_callback(NULL),
62 _temporalLayers(0),
63 _seqNum(0),
64 _sendPID(0),
65 _receivedPID(0),
66 _switchLayer(false),
67 _currentRelayLayer(0),
68 _lastTimeMs(webrtc::TickTime::MillisecondTimestamp()),
69 _checkSSRC(false),
70 _lastSSRC(0),
71 _filterSSRC(false),
72 _SSRC(0),
73 _checkSequenceNumber(0),
74 _firstSequenceNumber(0),
75 _firstRTPTimestamp(0),
76 _lastSendRTPTimestamp(0),
77 _lastReceiveRTPTimestamp(0),
78 last_receive_time_(-1),
79 previous_drop_(false)
80 {
81 srand((int) webrtc::TickTime::MicrosecondTimestamp());
82 unsigned int tId = 0;
83 memset(&network_parameters_, 0, sizeof(NetworkParameters));
84 _thread.Start(tId);
85 }
86
~TbExternalTransport()87 TbExternalTransport::~TbExternalTransport()
88 {
89 _thread.SetNotAlive();
90 _event.Set();
91 if (_thread.Stop())
92 {
93 delete &_thread;
94 delete &_event;
95 }
96 for (std::list<VideoPacket*>::iterator it = _rtpPackets.begin();
97 it != _rtpPackets.end(); ++it) {
98 delete *it;
99 }
100 _rtpPackets.clear();
101 for (std::list<VideoPacket*>::iterator it = _rtcpPackets.begin();
102 it != _rtcpPackets.end(); ++it) {
103 delete *it;
104 }
105 _rtcpPackets.clear();
106 delete &_crit;
107 delete &_statCrit;
108 }
109
SendPacket(int channel,const void * data,int len)110 int TbExternalTransport::SendPacket(int channel, const void *data, int len)
111 {
112 // Parse timestamp from RTP header according to RFC 3550, section 5.1.
113 uint8_t* ptr = (uint8_t*)data;
114 uint8_t payload_type = ptr[1] & 0x7F;
115 uint32_t rtp_timestamp = ptr[4] << 24;
116 rtp_timestamp += ptr[5] << 16;
117 rtp_timestamp += ptr[6] << 8;
118 rtp_timestamp += ptr[7];
119 _crit.Enter();
120 if (_firstRTPTimestamp == 0) {
121 _firstRTPTimestamp = rtp_timestamp;
122 }
123 _crit.Leave();
124 if (_send_frame_callback != NULL &&
125 _lastSendRTPTimestamp != rtp_timestamp) {
126 _send_frame_callback->FrameSent(rtp_timestamp);
127 }
128 ++packet_counters_[payload_type];
129 _lastSendRTPTimestamp = rtp_timestamp;
130
131 if (_filterSSRC)
132 {
133 uint8_t* ptr = (uint8_t*)data;
134 uint32_t ssrc = ptr[8] << 24;
135 ssrc += ptr[9] << 16;
136 ssrc += ptr[10] << 8;
137 ssrc += ptr[11];
138 if (ssrc != _SSRC)
139 {
140 return len; // return len to avoid error in trace file
141 }
142 }
143 if (_temporalLayers) {
144 // parse out vp8 temporal layers
145 // 12 bytes RTP
146 uint8_t* ptr = (uint8_t*)data;
147
148 if (ptr[12] & 0x80 && // X-bit
149 ptr[13] & 0x20) // T-bit
150 {
151 int offset = 1;
152 if (ptr[13] & 0x80) // PID-bit
153 {
154 offset++;
155 if (ptr[14] & 0x80) // 2 byte PID
156 {
157 offset++;
158 }
159 }
160 if (ptr[13] & 0x40)
161 {
162 offset++;
163 }
164 unsigned char TID = (ptr[13 + offset] >> 5);
165 unsigned int timeMs = NowMs();
166
167 // Every 5 second switch layer
168 if (_lastTimeMs + 5000 < timeMs)
169 {
170 _lastTimeMs = timeMs;
171 _switchLayer = true;
172 }
173 // Switch at the non ref frame
174 if (_switchLayer && (ptr[12] & 0x20))
175 { // N-bit
176 _currentRelayLayer++;
177 if (_currentRelayLayer >= _temporalLayers)
178 _currentRelayLayer = 0;
179
180 _switchLayer = false;
181 printf("\t Switching to layer:%d\n", _currentRelayLayer);
182 }
183 if (_currentRelayLayer < TID)
184 {
185 return len; // return len to avoid error in trace file
186 }
187 if (ptr[14] & 0x80) // 2 byte PID
188 {
189 if(_receivedPID != ptr[15])
190 {
191 _sendPID++;
192 _receivedPID = ptr[15];
193 }
194 } else
195 {
196 if(_receivedPID != ptr[14])
197 {
198 _sendPID++;
199 _receivedPID = ptr[14];
200 }
201 }
202 }
203 }
204 _statCrit.Enter();
205 _rtpCount++;
206 _statCrit.Leave();
207
208 // Packet loss.
209 switch (network_parameters_.loss_model)
210 {
211 case (kNoLoss):
212 previous_drop_ = false;
213 break;
214 case (kUniformLoss):
215 previous_drop_ = UniformLoss(network_parameters_.packet_loss_rate);
216 break;
217 case (kGilbertElliotLoss):
218 previous_drop_ = GilbertElliotLoss(
219 network_parameters_.packet_loss_rate,
220 network_parameters_.burst_length);
221 break;
222 }
223 // Never drop packets from the first RTP timestamp (first frame)
224 // transmitted.
225 if (previous_drop_ && _firstRTPTimestamp != rtp_timestamp)
226 {
227 _statCrit.Enter();
228 _dropCount++;
229 _statCrit.Leave();
230 return len;
231 }
232
233 VideoPacket* newPacket = new VideoPacket();
234 memcpy(newPacket->packetBuffer, data, len);
235
236 if (_temporalLayers)
237 {
238 // rewrite seqNum
239 newPacket->packetBuffer[2] = _seqNum >> 8;
240 newPacket->packetBuffer[3] = _seqNum;
241 _seqNum++;
242
243 // rewrite PID
244 if (newPacket->packetBuffer[14] & 0x80) // 2 byte PID
245 {
246 newPacket->packetBuffer[14] = (_sendPID >> 8) | 0x80;
247 newPacket->packetBuffer[15] = _sendPID;
248 } else
249 {
250 newPacket->packetBuffer[14] = (_sendPID & 0x7f);
251 }
252 }
253 newPacket->length = len;
254 newPacket->channel = channel;
255
256 _crit.Enter();
257 // Add jitter and make sure receiveTime isn't lower than receive time of
258 // last frame.
259 int network_delay_ms = GaussianRandom(
260 network_parameters_.mean_one_way_delay,
261 network_parameters_.std_dev_one_way_delay);
262 newPacket->receiveTime = NowMs() + network_delay_ms;
263 if (newPacket->receiveTime < last_receive_time_) {
264 newPacket->receiveTime = last_receive_time_;
265 }
266 _rtpPackets.push_back(newPacket);
267 _event.Set();
268 _crit.Leave();
269 return len;
270 }
271
RegisterSendFrameCallback(SendFrameCallback * callback)272 void TbExternalTransport::RegisterSendFrameCallback(
273 SendFrameCallback* callback) {
274 _send_frame_callback = callback;
275 }
276
RegisterReceiveFrameCallback(ReceiveFrameCallback * callback)277 void TbExternalTransport::RegisterReceiveFrameCallback(
278 ReceiveFrameCallback* callback) {
279 _receive_frame_callback = callback;
280 }
281
282 // Set to 0 to disable.
SetTemporalToggle(unsigned char layers)283 void TbExternalTransport::SetTemporalToggle(unsigned char layers)
284 {
285 _temporalLayers = layers;
286 }
287
SendRTCPPacket(int channel,const void * data,int len)288 int TbExternalTransport::SendRTCPPacket(int channel, const void *data, int len)
289 {
290 _statCrit.Enter();
291 _rtcpCount++;
292 _statCrit.Leave();
293
294 VideoPacket* newPacket = new VideoPacket();
295 memcpy(newPacket->packetBuffer, data, len);
296 newPacket->length = len;
297 newPacket->channel = channel;
298
299 _crit.Enter();
300 int network_delay_ms = GaussianRandom(
301 network_parameters_.mean_one_way_delay,
302 network_parameters_.std_dev_one_way_delay);
303 newPacket->receiveTime = NowMs() + network_delay_ms;
304 _rtcpPackets.push_back(newPacket);
305 _event.Set();
306 _crit.Leave();
307 return len;
308 }
309
SetNetworkParameters(const NetworkParameters & network_parameters)310 void TbExternalTransport::SetNetworkParameters(
311 const NetworkParameters& network_parameters)
312 {
313 webrtc::CriticalSectionScoped cs(&_crit);
314 network_parameters_ = network_parameters;
315 }
316
SetSSRCFilter(uint32_t ssrc)317 void TbExternalTransport::SetSSRCFilter(uint32_t ssrc)
318 {
319 webrtc::CriticalSectionScoped cs(&_crit);
320 _filterSSRC = true;
321 _SSRC = ssrc;
322 }
323
ClearStats()324 void TbExternalTransport::ClearStats()
325 {
326 webrtc::CriticalSectionScoped cs(&_statCrit);
327 _rtpCount = 0;
328 _dropCount = 0;
329 _rtcpCount = 0;
330 packet_counters_.clear();
331 }
332
GetStats(int32_t & numRtpPackets,int32_t & numDroppedPackets,int32_t & numRtcpPackets,std::map<uint8_t,int> * packet_counters)333 void TbExternalTransport::GetStats(int32_t& numRtpPackets,
334 int32_t& numDroppedPackets,
335 int32_t& numRtcpPackets,
336 std::map<uint8_t, int>* packet_counters)
337 {
338 webrtc::CriticalSectionScoped cs(&_statCrit);
339 numRtpPackets = _rtpCount;
340 numDroppedPackets = _dropCount;
341 numRtcpPackets = _rtcpCount;
342 *packet_counters = packet_counters_;
343 }
344
EnableSSRCCheck()345 void TbExternalTransport::EnableSSRCCheck()
346 {
347 webrtc::CriticalSectionScoped cs(&_statCrit);
348 _checkSSRC = true;
349 }
350
ReceivedSSRC()351 unsigned int TbExternalTransport::ReceivedSSRC()
352 {
353 webrtc::CriticalSectionScoped cs(&_statCrit);
354 return _lastSSRC;
355 }
356
EnableSequenceNumberCheck()357 void TbExternalTransport::EnableSequenceNumberCheck()
358 {
359 webrtc::CriticalSectionScoped cs(&_statCrit);
360 _checkSequenceNumber = true;
361 }
362
GetFirstSequenceNumber()363 unsigned short TbExternalTransport::GetFirstSequenceNumber()
364 {
365 webrtc::CriticalSectionScoped cs(&_statCrit);
366 return _firstSequenceNumber;
367 }
368
EmptyQueue() const369 bool TbExternalTransport::EmptyQueue() const {
370 webrtc::CriticalSectionScoped cs(&_crit);
371 return _rtpPackets.empty() && _rtcpPackets.empty();
372 }
373
ViEExternalTransportRun(void * object)374 bool TbExternalTransport::ViEExternalTransportRun(void* object)
375 {
376 return static_cast<TbExternalTransport*>
377 (object)->ViEExternalTransportProcess();
378 }
ViEExternalTransportProcess()379 bool TbExternalTransport::ViEExternalTransportProcess()
380 {
381 unsigned int waitTime = KMaxWaitTimeMs;
382
383 VideoPacket* packet = NULL;
384
385 _crit.Enter();
386 while (!_rtpPackets.empty())
387 {
388 // Take first packet in queue
389 packet = _rtpPackets.front();
390 int64_t timeToReceive = 0;
391 if (packet)
392 {
393 timeToReceive = packet->receiveTime - NowMs();
394 }
395 else
396 {
397 // There should never be any empty packets in the list.
398 assert(false);
399 }
400 if (timeToReceive > 0)
401 {
402 // No packets to receive yet
403 if (timeToReceive < waitTime && timeToReceive > 0)
404 {
405 waitTime = (unsigned int) timeToReceive;
406 }
407 break;
408 }
409 _rtpPackets.pop_front();
410 _crit.Leave();
411
412 // Send to ViE
413 if (packet)
414 {
415 unsigned int ssrc = 0;
416 {
417 webrtc::CriticalSectionScoped cs(&_statCrit);
418 ssrc = ((packet->packetBuffer[8]) << 24);
419 ssrc += (packet->packetBuffer[9] << 16);
420 ssrc += (packet->packetBuffer[10] << 8);
421 ssrc += packet->packetBuffer[11];
422 if (_checkSSRC)
423 {
424 _lastSSRC = ((packet->packetBuffer[8]) << 24);
425 _lastSSRC += (packet->packetBuffer[9] << 16);
426 _lastSSRC += (packet->packetBuffer[10] << 8);
427 _lastSSRC += packet->packetBuffer[11];
428 _checkSSRC = false;
429 }
430 if (_checkSequenceNumber)
431 {
432 _firstSequenceNumber
433 = (unsigned char) packet->packetBuffer[2] << 8;
434 _firstSequenceNumber
435 += (unsigned char) packet->packetBuffer[3];
436 _checkSequenceNumber = false;
437 }
438 }
439 // Signal received packet of frame
440 uint8_t* ptr = (uint8_t*)packet->packetBuffer;
441 uint32_t rtp_timestamp = ptr[4] << 24;
442 rtp_timestamp += ptr[5] << 16;
443 rtp_timestamp += ptr[6] << 8;
444 rtp_timestamp += ptr[7];
445 if (_receive_frame_callback != NULL &&
446 _lastReceiveRTPTimestamp != rtp_timestamp) {
447 _receive_frame_callback->FrameReceived(rtp_timestamp);
448 }
449 _lastReceiveRTPTimestamp = rtp_timestamp;
450 int destination_channel = sender_channel_;
451 if (receive_channels_) {
452 SsrcChannelMap::iterator it = receive_channels_->find(ssrc);
453 if (it == receive_channels_->end()) {
454 return false;
455 }
456 destination_channel = it->second;
457 }
458 _vieNetwork.ReceivedRTPPacket(destination_channel,
459 packet->packetBuffer,
460 packet->length,
461 webrtc::PacketTime());
462 delete packet;
463 packet = NULL;
464 }
465 _crit.Enter();
466 }
467 _crit.Leave();
468 _crit.Enter();
469 while (!_rtcpPackets.empty())
470 {
471 // Take first packet in queue
472 packet = _rtcpPackets.front();
473 int64_t timeToReceive = 0;
474 if (packet)
475 {
476 timeToReceive = packet->receiveTime - NowMs();
477 }
478 else
479 {
480 // There should never be any empty packets in the list.
481 assert(false);
482 }
483 if (timeToReceive > 0)
484 {
485 // No packets to receive yet
486 if (timeToReceive < waitTime && timeToReceive > 0)
487 {
488 waitTime = (unsigned int) timeToReceive;
489 }
490 break;
491 }
492 _rtcpPackets.pop_front();
493 _crit.Leave();
494
495 // Send to ViE
496 if (packet)
497 {
498 uint8_t pltype = static_cast<uint8_t>(packet->packetBuffer[1]);
499 if (pltype == kSenderReportPayloadType) {
500 // Sender report.
501 if (receive_channels_) {
502 for (SsrcChannelMap::iterator it = receive_channels_->begin();
503 it != receive_channels_->end(); ++it) {
504 _vieNetwork.ReceivedRTCPPacket(it->second,
505 packet->packetBuffer,
506 packet->length);
507 }
508 } else {
509 _vieNetwork.ReceivedRTCPPacket(sender_channel_,
510 packet->packetBuffer,
511 packet->length);
512 }
513 } else if (pltype == kReceiverReportPayloadType) {
514 // Receiver report.
515 _vieNetwork.ReceivedRTCPPacket(sender_channel_,
516 packet->packetBuffer,
517 packet->length);
518 }
519 delete packet;
520 packet = NULL;
521 }
522 _crit.Enter();
523 }
524 _crit.Leave();
525 _event.Wait(waitTime + 1); // Add 1 ms to not call to early...
526 return true;
527 }
528
NowMs()529 int64_t TbExternalTransport::NowMs()
530 {
531 return webrtc::TickTime::MillisecondTimestamp();
532 }
533
UniformLoss(int loss_rate)534 bool TbExternalTransport::UniformLoss(int loss_rate) {
535 int dropThis = rand() % 100;
536 return (dropThis < loss_rate);
537 }
538
GilbertElliotLoss(int loss_rate,int burst_length)539 bool TbExternalTransport::GilbertElliotLoss(int loss_rate, int burst_length) {
540 // Simulate bursty channel (Gilbert model)
541 // (1st order) Markov chain model with memory of the previous/last
542 // packet state (loss or received)
543
544 // 0 = received state
545 // 1 = loss state
546
547 // probTrans10: if previous packet is lost, prob. to -> received state
548 // probTrans11: if previous packet is lost, prob. to -> loss state
549
550 // probTrans01: if previous packet is received, prob. to -> loss state
551 // probTrans00: if previous packet is received, prob. to -> received
552
553 // Map the two channel parameters (average loss rate and burst length)
554 // to the transition probabilities:
555 double probTrans10 = 100 * (1.0 / burst_length);
556 double probTrans11 = (100.0 - probTrans10);
557 double probTrans01 = (probTrans10 * ( loss_rate / (100.0 - loss_rate)));
558
559 // Note: Random loss (Bernoulli) model is a special case where:
560 // burstLength = 100.0 / (100.0 - _lossPct) (i.e., p10 + p01 = 100)
561
562 if (previous_drop_) {
563 // Previous packet was not received.
564 return UniformLoss(probTrans11);
565 } else {
566 return UniformLoss(probTrans01);
567 }
568 }
569
570 #define PI 3.14159265
GaussianRandom(int mean_ms,int standard_deviation_ms)571 int TbExternalTransport::GaussianRandom(int mean_ms,
572 int standard_deviation_ms) {
573 // Creating a Normal distribution variable from two independent uniform
574 // variables based on the Box-Muller transform.
575 double uniform1 = (rand() + 1.0) / (RAND_MAX + 1.0);
576 double uniform2 = (rand() + 1.0) / (RAND_MAX + 1.0);
577 return static_cast<int>(mean_ms + standard_deviation_ms *
578 sqrt(-2 * log(uniform1)) * cos(2 * PI * uniform2));
579 }
580