-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathrtp_service.cpp
144 lines (122 loc) · 3.54 KB
/
rtp_service.cpp
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include "media.h"
#include "rtp_service.h"
#include <boost\bind.hpp>
using namespace boost;
using namespace boost::asio;
namespace media
{
rtp_service::rtp_service(io_service& io)
: io_strand(io), c1(io_strand), c2(io_strand), rtp(&c1), rtcp(&c2), rtcp_timer(io), started(false)
{
}
rtp_service::~rtp_service()
{
stop();
}
void rtp_service::open(const boost::asio::ip::address& iface, int& rtp_port, int& rtcp_port)
{
if (rtp_port == 0 && rtcp_port == 0)
{
int port1 = 0;
int port2 = 0;
for (int i = 0; i < 10; i++)
{
c1.open(iface, port1);
port2 = port1 + 1;
if (c2.try_open(iface, port2))
{
if (port1 % 2 == 0)
{
rtp_port = port1;
rtcp_port = port2;
}
else
{
rtp_port = port2;
rtcp_port = port1;
}
return;
}
}
throw std::exception("Failed to allocate RTP/RTCP port pair");
}
else
{
c1.open(iface, rtp_port);
c2.open(iface, rtcp_port);
}
}
void rtp_service::start()
{
if (!started)
{
dbg("Starting IO for stream");
ntp_start_time = get_ntp_time();
rtp_start_time = get_rtp_time(ntp_start_time);
started = true;
}
}
void rtp_service::stop()
{
if (started)
{
dbg("Stopping IO");
io_strand.post(boost::bind(&rtp_service::stop_request_received, this));
started = false;
}
}
void rtp_service::stop_request_received()
{
rtcp_timer.cancel();
c1.close();
c2.close();
}
uint32_t rtp_service::get_rtp_time(const ntp_time_t& ntp_time)
{
return rtp_start_time +
(ntp_time.fractional - ntp_start_time.fractional);
}
uint32_t rtp_service::get_rtp_start() { return rtp_start_time; }
void rtp_service::set_rtcp_peer(const boost::asio::ip::udp::endpoint& ep) { rtcp->set_peer(ep); }
void rtp_service::set_rtp_peer(const boost::asio::ip::udp::endpoint& ep) { rtp->set_peer(ep); }
void rtp_service::send_rtp(rtp_packet& pkt)
{
rtp->send(pkt.data(), pkt.size());
}
void rtp_service::send_rtcp(rtcp_packet& pkt)
{
rtcp->send(pkt.data(), pkt.compound_size());
}
void rtp_service::receive_rtp(std::function<void(rtp_packet&)> cb)
{
rtp->async_receive([cb](void* data, size_t size)
{
rtp_packet pkt(data, size);
cb(pkt);
});
}
void rtp_service::receive_rtcp(std::function<void(rtcp_packet&)> cb)
{
rtcp->async_receive([cb](void* data, size_t size)
{
rtcp_packet pkt(data, size);
cb(pkt);
});
}
void rtp_service::start_timer(int ms, std::function<void()> cb)
{
rtcp_timer.expires_from_now(boost::posix_time::milliseconds(ms));
rtcp_timer.async_wait(io_strand.wrap([cb](const boost::system::error_code& ec)
{
if (!ec) cb();
}));
}
void rtp_service::post(std::function<void()> cb)
{
io_strand.post(cb);
}
std::string rtp_service::to_string()
{
return "RTP " + rtp->to_string() + ", RTCP " + rtcp->to_string();
}
}