SRT improvements:
- Made SRT support optional - Make build options visible in cmake-gui - Improved generic connection stats for outputs - Added streamid handling configuration for MistInTSSRT - Push input support over SRT - Fixed support for SRT settings in push outputs - Fix parsing of SRT-passed stream names - Fixed hostnames in MistOutTSSRT, fixed PUSH_REWRITE trigger payload - Opus support in TS-SRT - Fixed SRT socket stats, fixed SRT socket address logic, improved SRT socket rolling restart support - Fixed SRT push deny
This commit is contained in:
parent
19199cbff8
commit
0bd5d742f6
19 changed files with 686 additions and 347 deletions
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include "config.h"
|
||||
#include "defines.h"
|
||||
#include "lib/socket_srt.h"
|
||||
#include "stream.h"
|
||||
#include "timing.h"
|
||||
#include "tinythread.h"
|
||||
|
@ -39,7 +38,6 @@
|
|||
bool Util::Config::is_active = false;
|
||||
bool Util::Config::is_restarting = false;
|
||||
static Socket::Server *serv_sock_pointer = 0;
|
||||
static Socket::SRTServer *serv_srt_sock_pointer = 0; ///< Holds a pointer to SRT Server, if it is connected
|
||||
uint32_t Util::printDebugLevel = DEBUG;
|
||||
std::string Util::streamName;
|
||||
char Util::exitReason[256] ={0};
|
||||
|
@ -55,13 +53,6 @@ void Util::logExitReason(const char *format, ...){
|
|||
std::string Util::listenInterface;
|
||||
uint32_t Util::listenPort = 0;
|
||||
|
||||
// Sets pointer to the SRT Server, for proper cleanup later.
|
||||
//
|
||||
// Currently used for TSSRT Input only, as this doesn't use the config library to setup a listener
|
||||
void Util::Config::registerSRTSockPtr(Socket::SRTServer *ptr){
|
||||
serv_srt_sock_pointer = ptr;
|
||||
}
|
||||
|
||||
Util::Config::Config(){
|
||||
// global options here
|
||||
vals["debug"]["long"] = "debug";
|
||||
|
@ -331,23 +322,6 @@ struct callbackData{
|
|||
int (*cb)(Socket::Connection &);
|
||||
};
|
||||
|
||||
// As above, but using an SRT Connection
|
||||
struct callbackSRTData{
|
||||
Socket::SRTConnection *sock;
|
||||
int (*cb)(Socket::SRTConnection &);
|
||||
};
|
||||
|
||||
// Callback for SRT-serving threads
|
||||
static void callThreadCallbackSRT(void *cDataArg){
|
||||
INSANE_MSG("Thread for %p started", cDataArg);
|
||||
callbackSRTData *cData = (callbackSRTData *)cDataArg;
|
||||
cData->cb(*(cData->sock));
|
||||
cData->sock->close();
|
||||
delete cData->sock;
|
||||
delete cData;
|
||||
INSANE_MSG("Thread for %p ended", cDataArg);
|
||||
}
|
||||
|
||||
static void callThreadCallback(void *cDataArg){
|
||||
INSANE_MSG("Thread for %p started", cDataArg);
|
||||
callbackData *cData = (callbackData *)cDataArg;
|
||||
|
@ -430,53 +404,6 @@ int Util::Config::serveThreadedSocket(int (*callback)(Socket::Connection &)){
|
|||
return r;
|
||||
}
|
||||
|
||||
// This is a THREADED server!! Fork does not work as the SRT library itself already starts up a
|
||||
// thread, and forking after thread creation messes up all control flow internal to the library.
|
||||
int Util::Config::serveSRTSocket(int (*callback)(Socket::SRTConnection &S)){
|
||||
Socket::SRTServer server_socket;
|
||||
if (vals.isMember("port") && vals.isMember("interface")){
|
||||
server_socket = Socket::SRTServer(getInteger("port"), getString("interface"), false, "output");
|
||||
}
|
||||
if (!server_socket.connected()){
|
||||
DEVEL_MSG("Failure to open socket");
|
||||
return 1;
|
||||
}
|
||||
serv_srt_sock_pointer = &server_socket;
|
||||
activate();
|
||||
if (server_socket.getSocket()){
|
||||
int oldSock = server_socket.getSocket();
|
||||
if (!dup2(oldSock, 0)){
|
||||
server_socket = Socket::SRTServer(0);
|
||||
close(oldSock);
|
||||
}
|
||||
}
|
||||
int r = SRTServer(server_socket, callback);
|
||||
serv_srt_sock_pointer = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
int Util::Config::SRTServer(Socket::SRTServer &server_socket, int (*callback)(Socket::SRTConnection &)){
|
||||
Util::Procs::socketList.insert(server_socket.getSocket());
|
||||
while (is_active && server_socket.connected()){
|
||||
Socket::SRTConnection S = server_socket.accept(false, "output");
|
||||
if (S.connected()){// check if the new connection is valid
|
||||
callbackSRTData *cData = new callbackSRTData;
|
||||
cData->sock = new Socket::SRTConnection(S);
|
||||
cData->cb = callback;
|
||||
// spawn a new thread for this connection
|
||||
tthread::thread T(callThreadCallbackSRT, (void *)cData);
|
||||
// detach it, no need to keep track of it anymore
|
||||
T.detach();
|
||||
HIGH_MSG("Spawned new thread for socket %i", S.getSocket());
|
||||
}else{
|
||||
Util::sleep(10); // sleep 10ms
|
||||
}
|
||||
}
|
||||
Util::Procs::socketList.erase(server_socket.getSocket());
|
||||
if (!is_restarting){server_socket.close();}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Util::Config::serveForkedSocket(int (*callback)(Socket::Connection &S)){
|
||||
Socket::Server server_socket;
|
||||
if (Socket::checkTrueSocket(0)){
|
||||
|
@ -541,8 +468,6 @@ void Util::Config::signal_handler(int signum, siginfo_t *sigInfo, void *ignore){
|
|||
case SIGHUP:
|
||||
case SIGTERM:
|
||||
if (serv_sock_pointer){serv_sock_pointer->close();}
|
||||
// Close the srt server as well, if set
|
||||
if (serv_srt_sock_pointer){serv_srt_sock_pointer->close();}
|
||||
#if DEBUG >= DLVL_DEVEL
|
||||
static int ctr = 0;
|
||||
if (!is_active && ++ctr > 4){BACKTRACE;}
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#endif
|
||||
|
||||
#include "json.h"
|
||||
#include "socket_srt.h"
|
||||
#include <signal.h>
|
||||
#include <string>
|
||||
|
||||
|
@ -42,7 +41,6 @@ namespace Util{
|
|||
int64_t getInteger(std::string optname);
|
||||
bool getBool(std::string optname);
|
||||
void activate();
|
||||
void registerSRTSockPtr(Socket::SRTServer *ptr);
|
||||
int threadServer(Socket::Server &server_socket, int (*callback)(Socket::Connection &S));
|
||||
int forkServer(Socket::Server &server_socket, int (*callback)(Socket::Connection &S));
|
||||
int serveThreadedSocket(int (*callback)(Socket::Connection &S));
|
||||
|
@ -51,9 +49,6 @@ namespace Util{
|
|||
void addOptionsFromCapabilities(const JSON::Value &capabilities);
|
||||
void addBasicConnectorOptions(JSON::Value &capabilities);
|
||||
void addConnectorOptions(int port, JSON::Value &capabilities);
|
||||
|
||||
int serveSRTSocket(int (*callback)(Socket::SRTConnection &S));
|
||||
int SRTServer(Socket::SRTServer &server_socket, int (*callback)(Socket::SRTConnection &S));
|
||||
};
|
||||
|
||||
/// The interface address the current serveSocket function is listening on
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "defines.h"
|
||||
#include "lib/http_parser.h"
|
||||
#include "socket_srt.h"
|
||||
#include "json.h"
|
||||
#include "timing.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
|
@ -69,13 +71,20 @@ namespace Socket{
|
|||
return interpretSRTMode(params.count("mode") ? params.at("mode") : "default", u.host, "");
|
||||
}
|
||||
|
||||
SRTConnection::SRTConnection(){initializeEmpty();}
|
||||
SRTConnection::SRTConnection(){
|
||||
initializeEmpty();
|
||||
lastGood = Util::bootMS();
|
||||
}
|
||||
|
||||
SRTConnection::SRTConnection(const std::string &_host, int _port, const std::string &_direction,
|
||||
const std::map<std::string, std::string> &_params){
|
||||
connect(_host, _port, _direction, _params);
|
||||
}
|
||||
|
||||
SRTConnection::SRTConnection(SRTSOCKET alreadyConnected){
|
||||
sock = alreadyConnected;
|
||||
}
|
||||
|
||||
std::string SRTConnection::getStreamName(){
|
||||
int sNameLen = 512;
|
||||
char sName[sNameLen];
|
||||
|
@ -84,29 +93,89 @@ namespace Socket{
|
|||
return "";
|
||||
}
|
||||
|
||||
/// Updates the downbuffer internal variable.
|
||||
/// Returns true if new data was received, false otherwise.
|
||||
std::string SRTConnection::RecvNow(){
|
||||
char recvbuf[5000];
|
||||
std::string SRTConnection::getBinHost(){
|
||||
char tmpBuffer[17] = "\000\000\000\000\000\000\000\000\000\000\377\377\000\000\000\000";
|
||||
switch (remoteaddr.sin6_family){
|
||||
case AF_INET:
|
||||
memcpy(tmpBuffer + 12, &(reinterpret_cast<const sockaddr_in *>(&remoteaddr)->sin_addr.s_addr), 4);
|
||||
break;
|
||||
case AF_INET6: memcpy(tmpBuffer, &(remoteaddr.sin6_addr.s6_addr), 16); break;
|
||||
default: return ""; break;
|
||||
}
|
||||
return std::string(tmpBuffer, 16);
|
||||
}
|
||||
|
||||
size_t SRTConnection::RecvNow(){
|
||||
|
||||
bool blockState = blocking;
|
||||
setBlocking(true);
|
||||
if (!blockState){setBlocking(true);}
|
||||
|
||||
SRT_MSGCTRL mc = srt_msgctrl_default;
|
||||
int32_t receivedBytes = srt_recvmsg2(sock, recvbuf, 5000, &mc);
|
||||
|
||||
if (prev_pktseq != 0 && (mc.pktseq - prev_pktseq > 1)){WARN_MSG("Packet lost");}
|
||||
//if (prev_pktseq != 0 && (mc.pktseq - prev_pktseq > 1)){WARN_MSG("Packet lost");}
|
||||
prev_pktseq = mc.pktseq;
|
||||
|
||||
setBlocking(blockState);
|
||||
if (!blockState){setBlocking(blockState);}
|
||||
if (receivedBytes == -1){
|
||||
int err = srt_getlasterror(0);
|
||||
if (err == SRT_ECONNLOST){
|
||||
close();
|
||||
return 0;
|
||||
}
|
||||
if (err == SRT_ENOCONN){
|
||||
if (Util::bootMS() > lastGood + 5000){
|
||||
ERROR_MSG("SRT connection timed out - closing");
|
||||
close();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
ERROR_MSG("Unable to receive data over socket: %s", srt_getlasterror_str());
|
||||
if (srt_getsockstate(sock) != SRTS_CONNECTED){close();}
|
||||
return "";
|
||||
return 0;
|
||||
}
|
||||
if (receivedBytes == 0){
|
||||
close();
|
||||
}else{
|
||||
lastGood = Util::bootMS();
|
||||
}
|
||||
|
||||
srt_bstats(sock, &performanceMonitor, false);
|
||||
return std::string(recvbuf, receivedBytes);
|
||||
return receivedBytes;
|
||||
}
|
||||
|
||||
///Attempts a read, obeying the current blocking setting.
|
||||
///May result in socket being disconnected when connection was lost during read.
|
||||
///Returns amount of bytes actually read
|
||||
size_t SRTConnection::Recv(){
|
||||
SRT_MSGCTRL mc = srt_msgctrl_default;
|
||||
int32_t receivedBytes = srt_recvmsg2(sock, recvbuf, 5000, &mc);
|
||||
prev_pktseq = mc.pktseq;
|
||||
if (receivedBytes == -1){
|
||||
int err = srt_getlasterror(0);
|
||||
if (err == SRT_EASYNCRCV){return 0;}
|
||||
if (err == SRT_ECONNLOST){
|
||||
close();
|
||||
return 0;
|
||||
}
|
||||
if (err == SRT_ENOCONN){
|
||||
if (Util::bootMS() > lastGood + 5000){
|
||||
ERROR_MSG("SRT connection timed out - closing");
|
||||
close();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
ERROR_MSG("Unable to receive data over socket: %s", srt_getlasterror_str());
|
||||
if (srt_getsockstate(sock) != SRTS_CONNECTED){close();}
|
||||
return 0;
|
||||
}
|
||||
if (receivedBytes == 0){
|
||||
close();
|
||||
}else{
|
||||
lastGood = Util::bootMS();
|
||||
}
|
||||
srt_bstats(sock, &performanceMonitor, false);
|
||||
return receivedBytes;
|
||||
}
|
||||
|
||||
void SRTConnection::connect(const std::string &_host, int _port, const std::string &_direction,
|
||||
|
@ -143,6 +212,7 @@ namespace Socket{
|
|||
HIGH_MSG("Going to connect sock %d", sock);
|
||||
if (srt_connect(sock, psa, sizeof sa) == SRT_ERROR){
|
||||
srt_close(sock);
|
||||
sock = -1;
|
||||
ERROR_MSG("Can't connect SRT Socket");
|
||||
return;
|
||||
}
|
||||
|
@ -153,6 +223,7 @@ namespace Socket{
|
|||
return;
|
||||
}
|
||||
INFO_MSG("Caller SRT socket %" PRId32 " success targetting %s:%u", sock, _host.c_str(), _port);
|
||||
lastGood = Util::bootMS();
|
||||
return;
|
||||
}
|
||||
if (modeName == "listener"){
|
||||
|
@ -163,14 +234,17 @@ namespace Socket{
|
|||
|
||||
if (srt_bind(sock, psa, sizeof sa) == SRT_ERROR){
|
||||
srt_close(sock);
|
||||
ERROR_MSG("Can't connect SRT Socket");
|
||||
sock = -1;
|
||||
ERROR_MSG("Can't connect SRT Socket: %s", srt_getlasterror_str());
|
||||
return;
|
||||
}
|
||||
if (srt_listen(sock, 1) == SRT_ERROR){
|
||||
srt_close(sock);
|
||||
sock = -1;
|
||||
ERROR_MSG("Can not listen on Socket");
|
||||
}
|
||||
INFO_MSG("Listener SRT socket sucess @ %s:%u", _host.c_str(), _port);
|
||||
lastGood = Util::bootMS();
|
||||
return;
|
||||
}
|
||||
if (modeName == "rendezvous"){
|
||||
|
@ -182,6 +256,7 @@ namespace Socket{
|
|||
|
||||
if (srt_bind(sock, psa, sizeof sa) == SRT_ERROR){
|
||||
srt_close(sock);
|
||||
sock = -1;
|
||||
ERROR_MSG("Can't connect SRT Socket");
|
||||
return;
|
||||
}
|
||||
|
@ -191,6 +266,7 @@ namespace Socket{
|
|||
|
||||
if (srt_connect(sock, psb, sizeof sb) == SRT_ERROR){
|
||||
srt_close(sock);
|
||||
sock = -1;
|
||||
ERROR_MSG("Can't connect SRT Socket");
|
||||
return;
|
||||
}
|
||||
|
@ -200,6 +276,7 @@ namespace Socket{
|
|||
return;
|
||||
}
|
||||
INFO_MSG("Rendezvous SRT socket sucess @ %s:%u", _host.c_str(), _port);
|
||||
lastGood = Util::bootMS();
|
||||
return;
|
||||
}
|
||||
ERROR_MSG("Invalid mode parameter. Use 'client' or 'server'");
|
||||
|
@ -220,8 +297,23 @@ namespace Socket{
|
|||
int res = srt_sendmsg2(sock, data, len, NULL);
|
||||
|
||||
if (res == SRT_ERROR){
|
||||
int err = srt_getlasterror(0);
|
||||
//Do not report normal connection lost errors
|
||||
if (err == SRT_ECONNLOST){
|
||||
close();
|
||||
return;
|
||||
}
|
||||
if (err == SRT_ENOCONN){
|
||||
if (Util::bootMS() > lastGood + 5000){
|
||||
ERROR_MSG("SRT connection timed out - closing");
|
||||
close();
|
||||
}
|
||||
return;
|
||||
}
|
||||
ERROR_MSG("Unable to send data over socket %" PRId32 ": %s", sock, srt_getlasterror_str());
|
||||
if (srt_getsockstate(sock) != SRTS_CONNECTED){close();}
|
||||
}else{
|
||||
lastGood = Util::bootMS();
|
||||
}
|
||||
srt_bstats(sock, &performanceMonitor, false);
|
||||
}
|
||||
|
@ -236,16 +328,16 @@ namespace Socket{
|
|||
uint64_t SRTConnection::dataDown(){return performanceMonitor.byteRecvTotal;}
|
||||
|
||||
uint64_t SRTConnection::packetCount(){
|
||||
return (direction == "input" ? performanceMonitor.pktRecvTotal : performanceMonitor.pktSentTotal);
|
||||
return (direction == "output" ? performanceMonitor.pktSentTotal : performanceMonitor.pktRecvTotal);
|
||||
}
|
||||
|
||||
uint64_t SRTConnection::packetLostCount(){
|
||||
return (direction == "input" ? performanceMonitor.pktRcvLossTotal : performanceMonitor.pktSndLossTotal);
|
||||
return (direction == "output" ? performanceMonitor.pktSndLossTotal : performanceMonitor.pktRcvLossTotal);
|
||||
}
|
||||
|
||||
uint64_t SRTConnection::packetRetransmitCount(){
|
||||
//\todo This should be updated with pktRcvRetransTotal on the retrieving end once srt has implemented this.
|
||||
return (direction == "input" ? 0 : performanceMonitor.pktRetransTotal);
|
||||
return (direction == "output" ? performanceMonitor.pktRetransTotal : 0);
|
||||
}
|
||||
|
||||
void SRTConnection::initializeEmpty(){
|
||||
|
@ -259,10 +351,8 @@ namespace Socket{
|
|||
void SRTConnection::setBlocking(bool _blocking){
|
||||
if (_blocking == blocking){return;}
|
||||
// If we have an error setting the new blocking state, the state is unchanged so we return early.
|
||||
if (srt_setsockopt(sock, 0, (direction == "output" ? SRTO_SNDSYN : SRTO_RCVSYN), &_blocking,
|
||||
sizeof _blocking) == -1){
|
||||
return;
|
||||
}
|
||||
if (srt_setsockopt(sock, 0, SRTO_SNDSYN, &_blocking, sizeof _blocking) == -1){return;}
|
||||
if (srt_setsockopt(sock, 0, SRTO_RCVSYN, &_blocking, sizeof _blocking) == -1){return;}
|
||||
blocking = _blocking;
|
||||
}
|
||||
|
||||
|
@ -289,7 +379,7 @@ namespace Socket{
|
|||
|
||||
if (adapter == "" && modeName == "listener"){adapter = _host;}
|
||||
|
||||
tsbpdMode = ((params.count("tsbpd") && isFalseString(params.at("tsbpd"))) ? false : true);
|
||||
tsbpdMode = (params.count("tsbpd") && JSON::Value(params.at("tsbpd")).asBool());
|
||||
|
||||
outgoing_port = (params.count("port") ? strtol(params.at("port").c_str(), 0, 0) : 0);
|
||||
|
||||
|
@ -332,14 +422,11 @@ namespace Socket{
|
|||
|
||||
int SRTConnection::postConfigureSocket(){
|
||||
bool no = false;
|
||||
if (srt_setsockopt(sock, 0, (direction == "output" ? SRTO_SNDSYN : SRTO_RCVSYN), &no, sizeof no) == -1){
|
||||
return -1;
|
||||
}
|
||||
if (srt_setsockopt(sock, 0, SRTO_SNDSYN, &no, sizeof no) == -1){return -1;}
|
||||
if (srt_setsockopt(sock, 0, SRTO_RCVSYN, &no, sizeof no) == -1){return -1;}
|
||||
if (timeout){
|
||||
if (srt_setsockopt(sock, 0, (direction == "output" ? SRTO_SNDTIMEO : SRTO_RCVTIMEO), &timeout,
|
||||
sizeof timeout) == -1){
|
||||
return -1;
|
||||
}
|
||||
if (srt_setsockopt(sock, 0, SRTO_SNDTIMEO, &timeout, sizeof timeout) == -1){return -1;}
|
||||
if (srt_setsockopt(sock, 0, SRTO_RCVTIMEO, &timeout, sizeof timeout) == -1){return -1;}
|
||||
}
|
||||
std::string errMsg = configureSocketLoop(SRT::SockOpt::POST);
|
||||
if (errMsg.size()){
|
||||
|
@ -455,15 +542,7 @@ namespace Socket{
|
|||
}
|
||||
}break;
|
||||
case SRT::SockOpt::BOOL:{
|
||||
bool tmp;
|
||||
if (isFalseString(v)){
|
||||
tmp = true;
|
||||
}else if (isTrueString(v)){
|
||||
tmp = true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
val.b = tmp;
|
||||
val.b = JSON::Value(v).asBool();
|
||||
val.value = &val.b;
|
||||
val.size = sizeof val.b;
|
||||
}break;
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "socket.h"
|
||||
#include "url.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <srt/srt.h>
|
||||
|
||||
typedef std::map<std::string, int> SockOptVals;
|
||||
|
@ -13,15 +10,6 @@ typedef std::map<std::string, std::string> paramList;
|
|||
|
||||
namespace Socket{
|
||||
std::string interpretSRTMode(const HTTP::URL &u);
|
||||
|
||||
inline bool isFalseString(const std::string &_val){
|
||||
return _val == "0" || _val == "no" || _val == "off" || _val == "false";
|
||||
}
|
||||
|
||||
inline bool isTrueString(const std::string &_val){
|
||||
return _val == "1" || _val == "yes" || _val == "on" || _val == "true";
|
||||
}
|
||||
|
||||
sockaddr_in createInetAddr(const std::string &_host, int _port);
|
||||
|
||||
namespace SRT{
|
||||
|
@ -39,7 +27,7 @@ namespace Socket{
|
|||
class SRTConnection{
|
||||
public:
|
||||
SRTConnection();
|
||||
SRTConnection(SRTSOCKET alreadyConnected){sock = alreadyConnected;}
|
||||
SRTConnection(SRTSOCKET alreadyConnected);
|
||||
SRTConnection(const std::string &_host, int _port, const std::string &_direction = "input",
|
||||
const paramList &_params = paramList());
|
||||
|
||||
|
@ -52,7 +40,10 @@ namespace Socket{
|
|||
void setBlocking(bool blocking); ///< Set this socket to be blocking (true) or nonblocking (false).
|
||||
bool isBlocking(); ///< Check if this socket is blocking (true) or nonblocking (false).
|
||||
|
||||
std::string RecvNow();
|
||||
size_t RecvNow();
|
||||
size_t Recv();
|
||||
char recvbuf[5000]; ///< Buffer where received data is stored in
|
||||
|
||||
void SendNow(const std::string &data);
|
||||
void SendNow(const char *data, size_t len);
|
||||
|
||||
|
@ -73,7 +64,7 @@ namespace Socket{
|
|||
|
||||
struct sockaddr_in6 remoteaddr;
|
||||
std::string remotehost;
|
||||
|
||||
std::string getBinHost();
|
||||
private:
|
||||
SRTSOCKET sock;
|
||||
CBytePerfMon performanceMonitor;
|
||||
|
@ -81,10 +72,11 @@ namespace Socket{
|
|||
std::string host;
|
||||
int outgoing_port;
|
||||
int32_t prev_pktseq;
|
||||
uint64_t lastGood;
|
||||
|
||||
uint32_t chunkTransmitSize;
|
||||
|
||||
// From paramaeter parsing
|
||||
// From parameter parsing
|
||||
std::string adapter;
|
||||
std::string modeName;
|
||||
int timeout;
|
||||
|
@ -100,7 +92,7 @@ namespace Socket{
|
|||
bool blocking;
|
||||
};
|
||||
|
||||
/// This class is for easily setting up listening socket, either TCP or Unix.
|
||||
/// This class is for easily setting up a listening SRT socket
|
||||
class SRTServer{
|
||||
public:
|
||||
SRTServer();
|
||||
|
@ -130,7 +122,6 @@ namespace Socket{
|
|||
|
||||
class SocketOption{
|
||||
public:
|
||||
//{"enforcedencryption", 0, SRTO_ENFORCEDENCRYPTION, SRT::SockOpt::PRE, SRT::SockOpt::BOOL, nullptr},
|
||||
SocketOption(const std::string &_name, int _protocol, int _symbol, SRT::SockOpt::Binding _binding,
|
||||
SRT::SockOpt::Type _type, const SockOptVals &_values = SockOptVals())
|
||||
: name(_name), protocol(_protocol), symbol(_symbol), binding(_binding), type(_type),
|
||||
|
@ -142,11 +133,8 @@ namespace Socket{
|
|||
SRT::SockOpt::Binding binding;
|
||||
SRT::SockOpt::Type type;
|
||||
SockOptVals valmap;
|
||||
|
||||
bool apply(int socket, const std::string &value, bool isSrtOpt = true);
|
||||
|
||||
static int setSo(int socket, int protocol, int symbol, const void *data, size_t size, bool isSrtOpt = true);
|
||||
|
||||
bool extract(const std::string &v, OptionValue &val, SRT::SockOpt::Type asType);
|
||||
};
|
||||
|
||||
|
|
|
@ -15,6 +15,51 @@ tthread::recursive_mutex tMutex;
|
|||
|
||||
namespace TS{
|
||||
|
||||
bool Assembler::assemble(Stream & TSStrm, char * ptr, size_t len){
|
||||
bool ret = false;
|
||||
size_t offset = 0;
|
||||
size_t amount = 188-leftData.size();
|
||||
if (leftData.size() && len >= amount){
|
||||
//Attempt to re-assemble a packet from the leftovers of last time + current head
|
||||
if (len == amount || ptr[amount] == 0x47){
|
||||
VERYHIGH_MSG("Assembled scrap packet");
|
||||
//Success!
|
||||
leftData.append(ptr, amount);
|
||||
tsBuf.FromPointer(leftData);
|
||||
TSStrm.add(tsBuf);
|
||||
ret = true;
|
||||
if (!TSStrm.isDataTrack(tsBuf.getPID())){TSStrm.parse(tsBuf.getPID());}
|
||||
offset = amount;
|
||||
leftData.assign(0,0);
|
||||
}
|
||||
//On failure, hope we might live to succeed another day
|
||||
}
|
||||
// Try to read full TS Packets
|
||||
// Watch out! We push here to a global, in order for threads to be able to access it.
|
||||
size_t junk = 0;
|
||||
while (offset < len){
|
||||
if (ptr[offset] == 0x47 && (offset+188 >= len || ptr[offset+188] == 0x47)){// check for sync byte
|
||||
if (junk){
|
||||
INFO_MSG("%zu bytes of non-sync-byte data received", junk);
|
||||
junk = 0;
|
||||
}
|
||||
if (offset + 188 <= len){
|
||||
tsBuf.FromPointer(ptr + offset);
|
||||
TSStrm.add(tsBuf);
|
||||
if (!TSStrm.isDataTrack(tsBuf.getPID())){TSStrm.parse(tsBuf.getPID());}
|
||||
ret = true;
|
||||
}else{
|
||||
leftData.assign(ptr + offset, len - offset);
|
||||
}
|
||||
offset += 188;
|
||||
}else{
|
||||
++junk;
|
||||
++offset;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ADTSRemainder::setRemainder(const aac::adts &p, const void *source, uint32_t avail, uint64_t bPos){
|
||||
if (!p.getCompleteSize()){return;}
|
||||
|
||||
|
|
|
@ -106,4 +106,13 @@ namespace TS{
|
|||
|
||||
void parsePES(size_t tid, bool finished = false);
|
||||
};
|
||||
|
||||
class Assembler{
|
||||
public:
|
||||
bool assemble(Stream & TSStrm, char * ptr, size_t len);
|
||||
private:
|
||||
Util::ResizeablePointer leftData;
|
||||
TS::Packet tsBuf;
|
||||
};
|
||||
|
||||
}// namespace TS
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue