1/*
2 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/modules/video_coding/main/test/mt_test_common.h"
12
13#include <math.h>
14
15#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
16#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
17#include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h"
18#include "webrtc/modules/utility/interface/rtp_dump.h"
19#include "webrtc/system_wrappers/interface/clock.h"
20
21namespace webrtc {
22
23TransportCallback::TransportCallback(Clock* clock, const char* filename)
24    : RTPSendCompleteCallback(clock, filename) {
25}
26
27TransportCallback::~TransportCallback()
28{
29    //
30}
31
32int
33TransportCallback::SendPacket(int channel, const void *data, int len)
34{
35    _sendCount++;
36    _totalSentLength += len;
37
38    if (_rtpDump != NULL)
39    {
40        if (_rtpDump->DumpPacket((const uint8_t*)data, len) != 0)
41        {
42            return -1;
43        }
44    }
45
46    bool transmitPacket = true;
47    // Off-line tests, don't drop first Key frame (approx.)
48    if (_sendCount > 20)
49    {
50        transmitPacket = PacketLoss();
51    }
52
53    Clock* clock = Clock::GetRealTimeClock();
54    int64_t now = clock->TimeInMilliseconds();
55    // Insert outgoing packet into list
56    if (transmitPacket)
57    {
58        RtpPacket* newPacket = new RtpPacket();
59        memcpy(newPacket->data, data, len);
60        newPacket->length = len;
61        // Simulate receive time = network delay + packet jitter
62        // simulated as a Normal distribution random variable with
63        // mean = networkDelay and variance = jitterVar
64        int32_t
65        simulatedDelay = (int32_t)NormalDist(_networkDelayMs,
66                                                   sqrt(_jitterVar));
67        newPacket->receiveTime = now + simulatedDelay;
68        _rtpPackets.push_back(newPacket);
69    }
70    return 0;
71}
72
73int
74TransportCallback::TransportPackets()
75{
76    // Are we ready to send packets to the receiver?
77    RtpPacket* packet = NULL;
78    Clock* clock = Clock::GetRealTimeClock();
79    int64_t now = clock->TimeInMilliseconds();
80
81    while (!_rtpPackets.empty())
82    {
83        // Take first packet in list
84        packet = _rtpPackets.front();
85        int64_t timeToReceive = packet->receiveTime - now;
86        if (timeToReceive > 0)
87        {
88            // No available packets to send
89            break;
90        }
91
92        _rtpPackets.pop_front();
93        // Send to receive side
94        RTPHeader header;
95        scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
96        if (!parser->Parse(packet->data, packet->length, &header)) {
97          delete packet;
98          return -1;
99        }
100        PayloadUnion payload_specific;
101        if (!rtp_payload_registry_->GetPayloadSpecifics(
102            header.payloadType, &payload_specific)) {
103          return -1;
104        }
105        if (!rtp_receiver_->IncomingRtpPacket(header, packet->data,
106                                              packet->length, payload_specific,
107                                              true))
108        {
109            delete packet;
110            return -1;
111        }
112        delete packet;
113        packet = NULL;
114    }
115    return 0; // OK
116}
117
118
119
120bool VCMProcessingThread(void* obj)
121{
122    SharedRTPState* state = static_cast<SharedRTPState*>(obj);
123    if (state->_vcm.TimeUntilNextProcess() <= 0)
124    {
125        if (state->_vcm.Process() < 0)
126        {
127            return false;
128        }
129    }
130    return true;
131}
132
133
134bool VCMDecodeThread(void* obj)
135{
136    SharedRTPState* state = static_cast<SharedRTPState*>(obj);
137    state->_vcm.Decode();
138    return true;
139}
140
141bool TransportThread(void *obj)
142{
143    SharedTransportState* state = static_cast<SharedTransportState*>(obj);
144    state->_transport.TransportPackets();
145    return true;
146}
147
148}  // namespace webrtc
149