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