summaryrefslogtreecommitdiffstats
blob: b8c443e41e01d1be900188a5039ff0be6b1e05cc (plain)
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
/*
 * 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 <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/numeric/conversion/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()));
}

}