forked from maaron/rtp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstream.cpp
121 lines (99 loc) · 3.18 KB
/
stream.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
#include "stdafx.h"
#include <algorithm>
#include "media.h"
#include "stream.h"
#include "rtp_packet.h"
#include "rtcp_packet.h"
#include <boost\bind.hpp>
#include "log.h"
namespace media
{
stream::stream(boost::asio::io_service& io, const char* cname)
: ssrc(rand32()),
connections(io),
rtcp(connections, ssrc, cname),
init(true)
{
}
stream::~stream()
{
// Make sure that the IO service is stopped before destroying child
// objects. The reason is that the rtcp object will be destroyed
// before the rtp_service object. However, RTCP may still have
// callbacks queued in the rtp_service's IO service. If a timer
// expires after the rtcp object is destroyed, bad problems can happen.
connections.stop();
}
void stream::open(const ip::address& iface, int& rtp_port, int& rtcp_port)
{
connections.open(iface, rtp_port, rtcp_port);
}
void stream::start()
{
connections.receive_rtp(boost::bind(
&stream::rtp_received, this, _1));
connections.receive_rtcp(boost::bind(
&stream::rtcp_received, this, _1));
connections.start();
}
void stream::start(const ip::udp::endpoint rtp_peer, const ip::udp::endpoint rtcp_peer)
{
connections.set_rtp_peer(rtp_peer);
connections.set_rtcp_peer(rtcp_peer);
connections.receive_rtp(boost::bind(
&stream::rtp_received, this, _1));
connections.receive_rtcp(boost::bind(
&stream::rtcp_received, this, _1));
connections.start();
}
void stream::bye()
{
connections.post(boost::bind(
&rtcp::bye, &rtcp));
}
void stream::stop()
{
connections.stop();
}
void stream::start_rtp_receive()
{
connections.receive_rtp(boost::bind(&stream::rtp_received, this, _1));
}
void stream::start_rtcp_receive()
{
connections.receive_rtcp(boost::bind(&stream::rtcp_received, this, _1));
}
void stream::rtp_received(rtp_packet& pkt)
{
rtcp.rtp_received(pkt);
loop_rtp_packet(pkt);
start_rtp_receive();
}
void stream::rtcp_received(rtcp_packet& pkt)
{
rtcp.rtcp_received(pkt);
start_rtcp_receive();
}
void stream::loop_rtp_packet(rtp_packet& pkt)
{
if (init)
{
// When we receive the first RTP packet from the peer, save the
// timestamp so that it can be used to determine the time deltas
// for future packets. This is needed in order to generate our own
// timestamps with the same intervals, but using a different
// (random) start time.
remote_start_time = pkt.get_timestamp();
init = false;
}
// Generate a local timestamp
pkt.set_timestamp(connections.get_rtp_start() +
(pkt.get_timestamp() - remote_start_time));
// Change the SSRC to our identifier
pkt.set_ssrc(ssrc);
// Send the packet back to the peer
connections.send_rtp(pkt);
// Notify RTCP so it can update its sender stats.
rtcp.rtp_sent(pkt);
}
}