1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
/*
* Copyright (c) 2012 Yoann Blein
* Licensed under the simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <Swiften/ScreenSharing/RTPSessionImpl.h>
#include <Swiften/ScreenSharing/RTPException.h>
//#include <algorithm>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/lexical_cast.hpp>
#include <rtppacket.h>
#include <rtpsourcedata.h>
#include <rtpsessionparams.h>
namespace Swift {
RTPSessionImpl::RTPSessionImpl(const HostAddressPort& remotePeer, PayloadType payloadType, int frequency)
: RTPSession(remotePeer, payloadType, frequency)
{
jrtplib::RTPExternalTransmissionParams transparams(&sender, 0);
jrtplib::RTPSessionParams sessparams;
// IMPORTANT: The local timestamp unit MUST be set, otherwise RTCP Sender Report info will be calculated wrong
sessparams.SetOwnTimestampUnit(1.0 / frequency);
checkError(session.Create(sessparams, &transparams, jrtplib::RTPTransmitter::ExternalProto));
//session.SetDefaultPayloadType(VP8);
packetInjecter = static_cast<jrtplib::RTPExternalTransmissionInfo*>(session.GetTransmissionInfo())->GetPacketInjector();
nativeAddressToJRTPAddress(remotePeer, jRTPRemotePeer);
}
RTPSessionImpl::~RTPSessionImpl()
{
}
void RTPSessionImpl::poll()
{
checkError(session.Poll()); // Required if threading disabled
}
void RTPSessionImpl::checkIncomingPackets()
{
// session.BeginDataAccess(); // useless without threading
if (session.GotoFirstSourceWithData() && session.GetCurrentSourceInfo()->GetRTPDataAddress()->IsSameAddress(&jRTPRemotePeer)) {
do {
jrtplib::RTPPacket *pack;
while ((pack = session.GetNextPacket()) != NULL) {
onIncomingPacket(pack->GetPayloadData(), pack->GetPayloadLength(), pack->HasMarker());
session.DeletePacket(pack);
}
} while (session.GotoNextSourceWithData());
}
// session.EndDataAccess(); // useless without threading
}
void RTPSessionImpl::sendPacket(const SafeByteArray& data, int timestampinc, bool marker)
{
checkError(session.SendPacket((void*)(&data[0]), data.size(), payloadType, marker, timestampinc));
poll();
}
void RTPSessionImpl::injectData(const SafeByteArray& data)
{
packetInjecter->InjectRTPorRTCP((void*)(&data[0]), data.size(), jRTPRemotePeer);
checkIncomingPackets();
poll();
}
void RTPSessionImpl::stop(int maxWaitMs)
{
session.BYEDestroy(jrtplib::RTPTime(0, maxWaitMs * 1000), "", 0);
// TODO: shutdown socket
}
void RTPSessionImpl::checkError(int rtperr) const
{
if (rtperr < 0)
throw RTPException(jrtplib::RTPGetErrorString(rtperr));
}
void RTPSessionImpl::nativeAddressToJRTPAddress(const HostAddressPort& hostAddressPort, jrtplib::RTPIPv4Address& jRTPAddress)
{
// Split address
std::vector<std::string> subStrings;
std::string ipAddress = hostAddressPort.getAddress().toString();
boost::algorithm::split(subStrings, ipAddress, boost::is_any_of("."));
// Cast sub strings array to array of byte
uint8_t ipNumbers[4];
for (int i = 0; i < std::min(4, (int)subStrings.size()); ++i)
ipNumbers[i] = boost::numeric_cast<uint8_t>(boost::lexical_cast<int>(subStrings[i]));
jRTPAddress.SetIP(ipNumbers);
jRTPAddress.SetPort(boost::numeric_cast<uint16_t>(hostAddressPort.getPort()));
}
}
|