forked from Haivision/srt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
transmitmedia.hpp
188 lines (150 loc) · 5.34 KB
/
transmitmedia.hpp
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/*
* SRT - Secure, Reliable, Transport
* Copyright (c) 2018 Haivision Systems Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
#ifndef INC_SRT_COMMON_TRANSMITMEDIA_HPP
#define INC_SRT_COMMON_TRANSMITMEDIA_HPP
#include <string>
#include <map>
#include <stdexcept>
#include "transmitbase.hpp"
#include <udt.h> // Needs access to CUDTException
using namespace std;
// Trial version of an exception. Try to implement later an official
// interruption mechanism in SRT using this.
struct TransmissionError: public std::runtime_error
{
TransmissionError(const std::string& arg):
std::runtime_error(arg)
{
}
};
class SrtCommon
{
protected:
bool m_output_direction = false; //< Defines which of SND or RCV option variant should be used, also to set SRT_SENDER for output
int m_timeout = 0; //< enforces using SRTO_SNDTIMEO or SRTO_RCVTIMEO, depending on @a m_output_direction
bool m_tsbpdmode = true;
int m_outgoing_port = 0;
string m_mode;
string m_adapter;
map<string, string> m_options; // All other options, as provided in the URI
SRTSOCKET m_sock = SRT_INVALID_SOCK;
SRTSOCKET m_bindsock = SRT_INVALID_SOCK;
bool IsUsable() { SRT_SOCKSTATUS st = srt_getsockstate(m_sock); return st > SRTS_INIT && st < SRTS_BROKEN; }
bool IsBroken() { return srt_getsockstate(m_sock) > SRTS_CONNECTED; }
public:
void InitParameters(string host, map<string,string> par);
void PrepareListener(string host, int port, int backlog);
void StealFrom(SrtCommon& src);
bool AcceptNewClient();
SRTSOCKET Socket() const { return m_sock; }
SRTSOCKET Listener() const { return m_bindsock; }
void Close();
protected:
void Error(string src);
void Init(string host, int port, map<string,string> par, bool dir_output);
virtual int ConfigurePost(SRTSOCKET sock);
virtual int ConfigurePre(SRTSOCKET sock);
void OpenClient(string host, int port);
void PrepareClient();
void SetupAdapter(const std::string& host, int port);
void ConnectClient(string host, int port);
void OpenServer(string host, int port)
{
PrepareListener(host, port, 1);
}
void OpenRendezvous(string adapter, string host, int port);
virtual ~SrtCommon();
};
class SrtSource: public Source, public SrtCommon
{
std::string hostport_copy;
public:
SrtSource(std::string host, int port, const std::map<std::string,std::string>& par);
SrtSource()
{
// Do nothing - create just to prepare for use
}
int Read(size_t chunk, MediaPacket& pkt, ostream& out_stats = cout) override;
/*
In this form this isn't needed.
Unblock if any extra settings have to be made.
virtual int ConfigurePre(UDTSOCKET sock) override
{
int result = SrtCommon::ConfigurePre(sock);
if ( result == -1 )
return result;
return 0;
}
*/
bool IsOpen() override { return IsUsable(); }
bool End() override { return IsBroken(); }
SRTSOCKET GetSRTSocket() const override
{
SRTSOCKET socket = SrtCommon::Socket();
if (socket == SRT_INVALID_SOCK)
socket = SrtCommon::Listener();
return socket;
}
bool AcceptNewClient() override { return SrtCommon::AcceptNewClient(); }
};
class SrtTarget: public Target, public SrtCommon
{
public:
SrtTarget(std::string host, int port, const std::map<std::string,std::string>& par)
{
Init(host, port, par, true);
}
SrtTarget() {}
int ConfigurePre(SRTSOCKET sock) override;
int Write(const char* data, size_t size, int64_t src_time, ostream &out_stats = cout) override;
bool IsOpen() override { return IsUsable(); }
bool Broken() override { return IsBroken(); }
size_t Still() override
{
size_t bytes;
int st = srt_getsndbuffer(m_sock, nullptr, &bytes);
if (st == -1)
return 0;
return bytes;
}
SRTSOCKET GetSRTSocket() const override
{
SRTSOCKET socket = SrtCommon::Socket();
if (socket == SRT_INVALID_SOCK)
socket = SrtCommon::Listener();
return socket;
}
bool AcceptNewClient() override { return SrtCommon::AcceptNewClient(); }
};
// This class is used when we don't know yet whether the given URI
// designates an effective listener or caller. So we create it, initialize,
// then we know what mode we'll be using.
//
// When caller, then we will do connect() using this object, then clone out
// a new object - of a direction specific class - which will steal the socket
// from this one and then roll the data. After this, this object is ready
// to connect again, and will create its own socket for that occasion, and
// the whole procedure repeats.
//
// When listener, then this object will be doing accept() and with every
// successful acceptation it will clone out a new object - of a direction
// specific class - which will steal just the connection socket from this
// object. This object will still live on and accept new connections and
// so on.
class SrtModel: public SrtCommon
{
public:
bool is_caller = false;
string m_host;
int m_port = 0;
SrtModel(string host, int port, map<string,string> par);
void Establish(std::string& name);
};
#endif