1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Use of this source code is governed by a BSD-style license 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * that can be found in the LICENSE file in the root of the source 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * tree. An additional intellectual property rights grant can be found 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * in the file PATENTS. All contributing project authors may 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 11281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/video_engine/test/libvietest/include/tb_external_transport.h" 12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 133f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org#include <assert.h> 143f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org 15137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org#include <math.h> 16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <stdio.h> // printf 17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <stdlib.h> // rand 18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#if defined(WEBRTC_LINUX) || defined(__linux__) 20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <string.h> 21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif 22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#if defined(WEBRTC_MAC) 233f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org#include <string.h> 24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif 25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 26281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 27281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/system_wrappers/interface/event_wrapper.h" 28281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/system_wrappers/interface/thread_wrapper.h" 29281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/system_wrappers/interface/tick_util.h" 30281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/video_engine/include/vie_network.h" 31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#if defined(_WIN32) 33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#pragma warning(disable: 4355) // 'this' : used in base member initializer list 34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif 35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgconst uint8_t kSenderReportPayloadType = 200; 37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgconst uint8_t kReceiverReportPayloadType = 201; 38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTbExternalTransport::TbExternalTransport( 40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org webrtc::ViENetwork& vieNetwork, 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int sender_channel, 42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org TbExternalTransport::SsrcChannelMap* receive_channels) 43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org : 44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org sender_channel_(sender_channel), 45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org receive_channels_(receive_channels), 46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _vieNetwork(vieNetwork), 47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _thread(*webrtc::ThreadWrapper::CreateThread( 48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ViEExternalTransportRun, this, webrtc::kHighPriority, 49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "AutotestTransport")), 50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _event(*webrtc::EventWrapper::Create()), 51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _crit(*webrtc::CriticalSectionWrapper::CreateCriticalSection()), 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _statCrit(*webrtc::CriticalSectionWrapper::CreateCriticalSection()), 53137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org network_parameters_(), 54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _rtpCount(0), 55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _rtcpCount(0), 56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _dropCount(0), 57eef4fd5c2263a5d9594c076c765abfe1e34b85f8stefan@webrtc.org packet_counters_(), 58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _rtpPackets(), 59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _rtcpPackets(), 60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _send_frame_callback(NULL), 61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _receive_frame_callback(NULL), 62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _temporalLayers(0), 63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _seqNum(0), 64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _sendPID(0), 65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _receivedPID(0), 66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _switchLayer(false), 67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentRelayLayer(0), 68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastTimeMs(webrtc::TickTime::MillisecondTimestamp()), 69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _checkSSRC(false), 70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastSSRC(0), 71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _filterSSRC(false), 72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _SSRC(0), 73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _checkSequenceNumber(0), 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _firstSequenceNumber(0), 75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _firstRTPTimestamp(0), 76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastSendRTPTimestamp(0), 77137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org _lastReceiveRTPTimestamp(0), 78574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org last_receive_time_(-1), 79574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org previous_drop_(false) 80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org srand((int) webrtc::TickTime::MicrosecondTimestamp()); 82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org unsigned int tId = 0; 83137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org memset(&network_parameters_, 0, sizeof(NetworkParameters)); 84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _thread.Start(tId); 85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgTbExternalTransport::~TbExternalTransport() 88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _thread.SetNotAlive(); 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _event.Set(); 91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_thread.Stop()) 92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete &_thread; 94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete &_event; 95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 96a9f28d54d55cadf2a900eeeff2612aeca8bdefe3mflodman@webrtc.org for (std::list<VideoPacket*>::iterator it = _rtpPackets.begin(); 97a9f28d54d55cadf2a900eeeff2612aeca8bdefe3mflodman@webrtc.org it != _rtpPackets.end(); ++it) { 98a9f28d54d55cadf2a900eeeff2612aeca8bdefe3mflodman@webrtc.org delete *it; 99a9f28d54d55cadf2a900eeeff2612aeca8bdefe3mflodman@webrtc.org } 100a9f28d54d55cadf2a900eeeff2612aeca8bdefe3mflodman@webrtc.org _rtpPackets.clear(); 101a9f28d54d55cadf2a900eeeff2612aeca8bdefe3mflodman@webrtc.org for (std::list<VideoPacket*>::iterator it = _rtcpPackets.begin(); 102a9f28d54d55cadf2a900eeeff2612aeca8bdefe3mflodman@webrtc.org it != _rtcpPackets.end(); ++it) { 103a9f28d54d55cadf2a900eeeff2612aeca8bdefe3mflodman@webrtc.org delete *it; 104a9f28d54d55cadf2a900eeeff2612aeca8bdefe3mflodman@webrtc.org } 105a9f28d54d55cadf2a900eeeff2612aeca8bdefe3mflodman@webrtc.org _rtcpPackets.clear(); 106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete &_crit; 107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete &_statCrit; 108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint TbExternalTransport::SendPacket(int channel, const void *data, int len) 111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Parse timestamp from RTP header according to RFC 3550, section 5.1. 11367879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org uint8_t* ptr = (uint8_t*)data; 114eef4fd5c2263a5d9594c076c765abfe1e34b85f8stefan@webrtc.org uint8_t payload_type = ptr[1] & 0x7F; 11567879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org uint32_t rtp_timestamp = ptr[4] << 24; 116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org rtp_timestamp += ptr[5] << 16; 117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org rtp_timestamp += ptr[6] << 8; 118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org rtp_timestamp += ptr[7]; 119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _crit.Enter(); 120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_firstRTPTimestamp == 0) { 121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _firstRTPTimestamp = rtp_timestamp; 122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _crit.Leave(); 124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_send_frame_callback != NULL && 125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastSendRTPTimestamp != rtp_timestamp) { 126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _send_frame_callback->FrameSent(rtp_timestamp); 127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 128eef4fd5c2263a5d9594c076c765abfe1e34b85f8stefan@webrtc.org ++packet_counters_[payload_type]; 129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastSendRTPTimestamp = rtp_timestamp; 130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_filterSSRC) 132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 13367879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org uint8_t* ptr = (uint8_t*)data; 13467879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org uint32_t ssrc = ptr[8] << 24; 135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ssrc += ptr[9] << 16; 136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ssrc += ptr[10] << 8; 137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ssrc += ptr[11]; 138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ssrc != _SSRC) 139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return len; // return len to avoid error in trace file 141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_temporalLayers) { 144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // parse out vp8 temporal layers 145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 12 bytes RTP 14667879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org uint8_t* ptr = (uint8_t*)data; 147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ptr[12] & 0x80 && // X-bit 149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ptr[13] & 0x20) // T-bit 150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int offset = 1; 152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ptr[13] & 0x80) // PID-bit 153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org offset++; 155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ptr[14] & 0x80) // 2 byte PID 156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org offset++; 158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ptr[13] & 0x40) 161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org offset++; 163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org unsigned char TID = (ptr[13 + offset] >> 5); 165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org unsigned int timeMs = NowMs(); 166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Every 5 second switch layer 168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_lastTimeMs + 5000 < timeMs) 169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastTimeMs = timeMs; 171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _switchLayer = true; 172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Switch at the non ref frame 174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_switchLayer && (ptr[12] & 0x20)) 175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { // N-bit 176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentRelayLayer++; 177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_currentRelayLayer >= _temporalLayers) 178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentRelayLayer = 0; 179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _switchLayer = false; 181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org printf("\t Switching to layer:%d\n", _currentRelayLayer); 182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_currentRelayLayer < TID) 184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return len; // return len to avoid error in trace file 186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ptr[14] & 0x80) // 2 byte PID 188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if(_receivedPID != ptr[15]) 190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _sendPID++; 192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _receivedPID = ptr[15]; 193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if(_receivedPID != ptr[14]) 197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _sendPID++; 199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _receivedPID = ptr[14]; 200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _statCrit.Enter(); 205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _rtpCount++; 206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _statCrit.Leave(); 207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 208574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org // Packet loss. 209574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org switch (network_parameters_.loss_model) 210574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org { 211574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org case (kNoLoss): 212574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org previous_drop_ = false; 213574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org break; 214574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org case (kUniformLoss): 215574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org previous_drop_ = UniformLoss(network_parameters_.packet_loss_rate); 216574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org break; 217574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org case (kGilbertElliotLoss): 218574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org previous_drop_ = GilbertElliotLoss( 219574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org network_parameters_.packet_loss_rate, 220574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org network_parameters_.burst_length); 221574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org break; 222574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org } 223574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org // Never drop packets from the first RTP timestamp (first frame) 224574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org // transmitted. 225574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org if (previous_drop_ && _firstRTPTimestamp != rtp_timestamp) 226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _statCrit.Enter(); 228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _dropCount++; 229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _statCrit.Leave(); 23039784c46c9562c6584ca0212e04ac219971b2c8fstefan@webrtc.org return len; 231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VideoPacket* newPacket = new VideoPacket(); 234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memcpy(newPacket->packetBuffer, data, len); 235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_temporalLayers) 237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // rewrite seqNum 239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org newPacket->packetBuffer[2] = _seqNum >> 8; 240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org newPacket->packetBuffer[3] = _seqNum; 241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _seqNum++; 242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // rewrite PID 244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (newPacket->packetBuffer[14] & 0x80) // 2 byte PID 245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org newPacket->packetBuffer[14] = (_sendPID >> 8) | 0x80; 247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org newPacket->packetBuffer[15] = _sendPID; 248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org newPacket->packetBuffer[14] = (_sendPID & 0x7f); 251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org newPacket->length = len; 254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org newPacket->channel = channel; 255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _crit.Enter(); 257137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org // Add jitter and make sure receiveTime isn't lower than receive time of 258137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org // last frame. 259137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org int network_delay_ms = GaussianRandom( 260137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org network_parameters_.mean_one_way_delay, 261137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org network_parameters_.std_dev_one_way_delay); 262137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org newPacket->receiveTime = NowMs() + network_delay_ms; 263137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org if (newPacket->receiveTime < last_receive_time_) { 264137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org newPacket->receiveTime = last_receive_time_; 265137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org } 266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _rtpPackets.push_back(newPacket); 267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _event.Set(); 268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _crit.Leave(); 269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return len; 270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid TbExternalTransport::RegisterSendFrameCallback( 273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SendFrameCallback* callback) { 274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _send_frame_callback = callback; 275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid TbExternalTransport::RegisterReceiveFrameCallback( 278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ReceiveFrameCallback* callback) { 279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _receive_frame_callback = callback; 280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Set to 0 to disable. 283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid TbExternalTransport::SetTemporalToggle(unsigned char layers) 284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _temporalLayers = layers; 286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint TbExternalTransport::SendRTCPPacket(int channel, const void *data, int len) 289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _statCrit.Enter(); 291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _rtcpCount++; 292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _statCrit.Leave(); 293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VideoPacket* newPacket = new VideoPacket(); 295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memcpy(newPacket->packetBuffer, data, len); 296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org newPacket->length = len; 297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org newPacket->channel = channel; 298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _crit.Enter(); 300137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org int network_delay_ms = GaussianRandom( 301137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org network_parameters_.mean_one_way_delay, 302137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org network_parameters_.std_dev_one_way_delay); 303137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org newPacket->receiveTime = NowMs() + network_delay_ms; 304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _rtcpPackets.push_back(newPacket); 305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _event.Set(); 306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _crit.Leave(); 307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return len; 308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 310137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.orgvoid TbExternalTransport::SetNetworkParameters( 311137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org const NetworkParameters& network_parameters) 312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org webrtc::CriticalSectionScoped cs(&_crit); 314137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org network_parameters_ = network_parameters; 315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 31767879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.orgvoid TbExternalTransport::SetSSRCFilter(uint32_t ssrc) 318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org webrtc::CriticalSectionScoped cs(&_crit); 320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _filterSSRC = true; 321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _SSRC = ssrc; 322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid TbExternalTransport::ClearStats() 325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org webrtc::CriticalSectionScoped cs(&_statCrit); 327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _rtpCount = 0; 328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _dropCount = 0; 329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _rtcpCount = 0; 330eef4fd5c2263a5d9594c076c765abfe1e34b85f8stefan@webrtc.org packet_counters_.clear(); 331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 33367879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.orgvoid TbExternalTransport::GetStats(int32_t& numRtpPackets, 33467879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org int32_t& numDroppedPackets, 335eef4fd5c2263a5d9594c076c765abfe1e34b85f8stefan@webrtc.org int32_t& numRtcpPackets, 336eef4fd5c2263a5d9594c076c765abfe1e34b85f8stefan@webrtc.org std::map<uint8_t, int>* packet_counters) 337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org webrtc::CriticalSectionScoped cs(&_statCrit); 339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org numRtpPackets = _rtpCount; 340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org numDroppedPackets = _dropCount; 341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org numRtcpPackets = _rtcpCount; 342eef4fd5c2263a5d9594c076c765abfe1e34b85f8stefan@webrtc.org *packet_counters = packet_counters_; 343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid TbExternalTransport::EnableSSRCCheck() 346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org webrtc::CriticalSectionScoped cs(&_statCrit); 348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _checkSSRC = true; 349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgunsigned int TbExternalTransport::ReceivedSSRC() 352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org webrtc::CriticalSectionScoped cs(&_statCrit); 354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _lastSSRC; 355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid TbExternalTransport::EnableSequenceNumberCheck() 358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org webrtc::CriticalSectionScoped cs(&_statCrit); 360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _checkSequenceNumber = true; 361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgunsigned short TbExternalTransport::GetFirstSequenceNumber() 364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org webrtc::CriticalSectionScoped cs(&_statCrit); 366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _firstSequenceNumber; 367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 369e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.orgbool TbExternalTransport::EmptyQueue() const { 370e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org webrtc::CriticalSectionScoped cs(&_crit); 371e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org return _rtpPackets.empty() && _rtcpPackets.empty(); 372e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org} 373e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org 374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool TbExternalTransport::ViEExternalTransportRun(void* object) 375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return static_cast<TbExternalTransport*> 377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (object)->ViEExternalTransportProcess(); 378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool TbExternalTransport::ViEExternalTransportProcess() 380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org unsigned int waitTime = KMaxWaitTimeMs; 382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VideoPacket* packet = NULL; 384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 385e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org _crit.Enter(); 386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (!_rtpPackets.empty()) 387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Take first packet in queue 389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org packet = _rtpPackets.front(); 39067879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org int64_t timeToReceive = 0; 391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (packet) 392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org timeToReceive = packet->receiveTime - NowMs(); 394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // There should never be any empty packets in the list. 398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(false); 399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (timeToReceive > 0) 401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // No packets to receive yet 403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (timeToReceive < waitTime && timeToReceive > 0) 404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org waitTime = (unsigned int) timeToReceive; 406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _rtpPackets.pop_front(); 410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _crit.Leave(); 411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Send to ViE 413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (packet) 414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org unsigned int ssrc = 0; 416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org webrtc::CriticalSectionScoped cs(&_statCrit); 418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ssrc = ((packet->packetBuffer[8]) << 24); 419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ssrc += (packet->packetBuffer[9] << 16); 420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ssrc += (packet->packetBuffer[10] << 8); 421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ssrc += packet->packetBuffer[11]; 422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_checkSSRC) 423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastSSRC = ((packet->packetBuffer[8]) << 24); 425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastSSRC += (packet->packetBuffer[9] << 16); 426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastSSRC += (packet->packetBuffer[10] << 8); 427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastSSRC += packet->packetBuffer[11]; 428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _checkSSRC = false; 429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_checkSequenceNumber) 431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _firstSequenceNumber 433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org = (unsigned char) packet->packetBuffer[2] << 8; 434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _firstSequenceNumber 435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org += (unsigned char) packet->packetBuffer[3]; 436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _checkSequenceNumber = false; 437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Signal received packet of frame 44067879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org uint8_t* ptr = (uint8_t*)packet->packetBuffer; 44167879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org uint32_t rtp_timestamp = ptr[4] << 24; 442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org rtp_timestamp += ptr[5] << 16; 443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org rtp_timestamp += ptr[6] << 8; 444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org rtp_timestamp += ptr[7]; 445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_receive_frame_callback != NULL && 446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastReceiveRTPTimestamp != rtp_timestamp) { 447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _receive_frame_callback->FrameReceived(rtp_timestamp); 448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastReceiveRTPTimestamp = rtp_timestamp; 450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int destination_channel = sender_channel_; 451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (receive_channels_) { 452b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SsrcChannelMap::iterator it = receive_channels_->find(ssrc); 453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (it == receive_channels_->end()) { 454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org destination_channel = it->second; 457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _vieNetwork.ReceivedRTPPacket(destination_channel, 459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org packet->packetBuffer, 460efeb8ce7e183005e557a2d107203e2057cec26a8wu@webrtc.org packet->length, 461efeb8ce7e183005e557a2d107203e2057cec26a8wu@webrtc.org webrtc::PacketTime()); 462b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete packet; 463b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org packet = NULL; 464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 465e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org _crit.Enter(); 466b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 467e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org _crit.Leave(); 468e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org _crit.Enter(); 469b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (!_rtcpPackets.empty()) 470b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Take first packet in queue 472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org packet = _rtcpPackets.front(); 47367879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org int64_t timeToReceive = 0; 474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (packet) 475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org timeToReceive = packet->receiveTime - NowMs(); 477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // There should never be any empty packets in the list. 481b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(false); 482b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (timeToReceive > 0) 484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // No packets to receive yet 486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (timeToReceive < waitTime && timeToReceive > 0) 487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 488b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org waitTime = (unsigned int) timeToReceive; 489b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 491b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 492b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _rtcpPackets.pop_front(); 493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _crit.Leave(); 494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Send to ViE 496b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (packet) 497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org uint8_t pltype = static_cast<uint8_t>(packet->packetBuffer[1]); 499b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (pltype == kSenderReportPayloadType) { 500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Sender report. 501b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (receive_channels_) { 502b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (SsrcChannelMap::iterator it = receive_channels_->begin(); 503b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org it != receive_channels_->end(); ++it) { 504b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _vieNetwork.ReceivedRTCPPacket(it->second, 505b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org packet->packetBuffer, 506b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org packet->length); 507b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 508b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else { 509b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _vieNetwork.ReceivedRTCPPacket(sender_channel_, 510b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org packet->packetBuffer, 511b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org packet->length); 512b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 513b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else if (pltype == kReceiverReportPayloadType) { 514b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Receiver report. 515b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _vieNetwork.ReceivedRTCPPacket(sender_channel_, 516b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org packet->packetBuffer, 517b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org packet->length); 518b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 519b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete packet; 520b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org packet = NULL; 521b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 522e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org _crit.Enter(); 523b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 524e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org _crit.Leave(); 525b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _event.Wait(waitTime + 1); // Add 1 ms to not call to early... 526b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 527b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 528b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 52967879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.orgint64_t TbExternalTransport::NowMs() 530b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 531b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return webrtc::TickTime::MillisecondTimestamp(); 532b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 533137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org 534574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.orgbool TbExternalTransport::UniformLoss(int loss_rate) { 535574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org int dropThis = rand() % 100; 536574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org return (dropThis < loss_rate); 537574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org} 538574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org 539574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.orgbool TbExternalTransport::GilbertElliotLoss(int loss_rate, int burst_length) { 540574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org // Simulate bursty channel (Gilbert model) 541574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org // (1st order) Markov chain model with memory of the previous/last 542574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org // packet state (loss or received) 543574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org 544574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org // 0 = received state 545574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org // 1 = loss state 546574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org 547574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org // probTrans10: if previous packet is lost, prob. to -> received state 548574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org // probTrans11: if previous packet is lost, prob. to -> loss state 549574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org 550574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org // probTrans01: if previous packet is received, prob. to -> loss state 551574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org // probTrans00: if previous packet is received, prob. to -> received 552574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org 553574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org // Map the two channel parameters (average loss rate and burst length) 554574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org // to the transition probabilities: 555574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org double probTrans10 = 100 * (1.0 / burst_length); 556574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org double probTrans11 = (100.0 - probTrans10); 557574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org double probTrans01 = (probTrans10 * ( loss_rate / (100.0 - loss_rate))); 558574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org 559574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org // Note: Random loss (Bernoulli) model is a special case where: 560574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org // burstLength = 100.0 / (100.0 - _lossPct) (i.e., p10 + p01 = 100) 561574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org 562574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org if (previous_drop_) { 563574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org // Previous packet was not received. 564574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org return UniformLoss(probTrans11); 565574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org } else { 566574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org return UniformLoss(probTrans01); 567574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org } 568574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org} 569574c33c65d0ff3d2502e0717ab6e1fdf46671365mikhal@webrtc.org 570137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org#define PI 3.14159265 571137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.orgint TbExternalTransport::GaussianRandom(int mean_ms, 572137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org int standard_deviation_ms) { 573137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org // Creating a Normal distribution variable from two independent uniform 574137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org // variables based on the Box-Muller transform. 575137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org double uniform1 = (rand() + 1.0) / (RAND_MAX + 1.0); 576137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org double uniform2 = (rand() + 1.0) / (RAND_MAX + 1.0); 577137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org return static_cast<int>(mean_ms + standard_deviation_ms * 578137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org sqrt(-2 * log(uniform1)) * cos(2 * PI * uniform2)); 579137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org} 580