Home | History | Annotate | Download | only in testbed
      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 
     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 
     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 
    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 
    272 void TbExternalTransport::RegisterSendFrameCallback(
    273     SendFrameCallback* callback) {
    274   _send_frame_callback = callback;
    275 }
    276 
    277 void TbExternalTransport::RegisterReceiveFrameCallback(
    278     ReceiveFrameCallback* callback) {
    279   _receive_frame_callback = callback;
    280 }
    281 
    282 // Set to 0 to disable.
    283 void TbExternalTransport::SetTemporalToggle(unsigned char layers)
    284 {
    285     _temporalLayers = layers;
    286 }
    287 
    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 
    310 void TbExternalTransport::SetNetworkParameters(
    311     const NetworkParameters& network_parameters)
    312 {
    313     webrtc::CriticalSectionScoped cs(&_crit);
    314     network_parameters_ = network_parameters;
    315 }
    316 
    317 void TbExternalTransport::SetSSRCFilter(uint32_t ssrc)
    318 {
    319     webrtc::CriticalSectionScoped cs(&_crit);
    320     _filterSSRC = true;
    321     _SSRC = ssrc;
    322 }
    323 
    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 
    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 
    345 void TbExternalTransport::EnableSSRCCheck()
    346 {
    347     webrtc::CriticalSectionScoped cs(&_statCrit);
    348     _checkSSRC = true;
    349 }
    350 
    351 unsigned int TbExternalTransport::ReceivedSSRC()
    352 {
    353     webrtc::CriticalSectionScoped cs(&_statCrit);
    354     return _lastSSRC;
    355 }
    356 
    357 void TbExternalTransport::EnableSequenceNumberCheck()
    358 {
    359     webrtc::CriticalSectionScoped cs(&_statCrit);
    360     _checkSequenceNumber = true;
    361 }
    362 
    363 unsigned short TbExternalTransport::GetFirstSequenceNumber()
    364 {
    365     webrtc::CriticalSectionScoped cs(&_statCrit);
    366     return _firstSequenceNumber;
    367 }
    368 
    369 bool TbExternalTransport::EmptyQueue() const {
    370   webrtc::CriticalSectionScoped cs(&_crit);
    371   return _rtpPackets.empty() && _rtcpPackets.empty();
    372 }
    373 
    374 bool TbExternalTransport::ViEExternalTransportRun(void* object)
    375 {
    376     return static_cast<TbExternalTransport*>
    377         (object)->ViEExternalTransportProcess();
    378 }
    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 
    529 int64_t TbExternalTransport::NowMs()
    530 {
    531     return webrtc::TickTime::MillisecondTimestamp();
    532 }
    533 
    534 bool TbExternalTransport::UniformLoss(int loss_rate) {
    535   int dropThis = rand() % 100;
    536   return (dropThis < loss_rate);
    537 }
    538 
    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
    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