11#include <QMutexLocker>
25#define LOC QString("SatIPSH[%1]: ").arg(m_inputId)
36 QMap<QString, SatIPStreamHandler*>::iterator it =
s_handlers.find(devname);
45 LOG(VB_RECORD, LOG_INFO,
46 QString(
"SatIPSH[%1]: Creating new stream handler for %2")
47 .arg(inputid).arg(devname));
53 (*it)->m_inputId = inputid;
55 LOG(VB_RECORD, LOG_INFO,
56 QString(
"SatIPSH[%1]: Using existing stream handler for %2").arg(inputid).arg(devname) +
57 QString(
" (%1 users)").arg(rcount));
72 LOG(VB_RECORD, LOG_ERR, QString(
"SatIPSH[%1]: Return(%2) not found")
73 .arg(inputid).arg(devname));
77 LOG(VB_RECORD, LOG_INFO, QString(
"SatIPSH[%1]: Return stream handler for %2 (%3 users)")
78 .arg(inputid).arg(devname).arg(*rit));
87 QMap<QString, SatIPStreamHandler*>::iterator it =
s_handlers.find(devname);
90 LOG(VB_RECORD, LOG_INFO, QString(
"SatIPSH[%1]: Closing handler for %2")
91 .arg(inputid).arg(devname));
99 LOG(VB_GENERAL, LOG_ERR,
100 QString(
"SatIPSH[%1] Error: Couldn't find handler for %2")
101 .arg(inputid).arg(devname));
115 LOG(VB_RECORD, LOG_DEBUG,
LOC +
116 QString(
"ctor for %2").arg(device));
121 uint preferred_port = 26420 + (2*inputid);
123 if (
m_dsocket->bind(QHostAddress::AnyIPv4,
125 QAbstractSocket::DefaultForPlatform))
131 if (
m_dsocket->bind(QHostAddress::AnyIPv4,
133 QAbstractSocket::DefaultForPlatform))
142 LOG(VB_GENERAL, LOG_INFO,
LOC +
143 QString(
"RTP socket bound to requested port %1").arg(
m_dport));
147 LOG(VB_GENERAL, LOG_WARNING,
LOC +
148 QString(
"Requested port %1 but RTP socket bound to port %2")
149 .arg(preferred_port).arg(
m_dport));
153 LOG(VB_GENERAL, LOG_ERR,
LOC +
154 QString(
"Failed to bind RTP socket"));
165 if (
m_csocket->bind(QHostAddress::AnyIPv4,
167 QAbstractSocket::DefaultForPlatform))
173 if (
m_csocket->bind(QHostAddress::AnyIPv4,
175 QAbstractSocket::DefaultForPlatform))
184 LOG(VB_GENERAL, LOG_INFO,
LOC +
185 QString(
"RTCP socket bound to requested port %1").arg(
m_cport));
189 LOG(VB_GENERAL, LOG_WARNING,
LOC +
190 QString(
"Requested port %1 but RTCP socket bound to port %2")
191 .arg(preferred_port).arg(
m_cport));
195 LOG(VB_GENERAL, LOG_ERR,
LOC +
196 QString(
"Failed to bind RTCP socket"));
205 const uint desiredsize = 8*1000*1000;
207 if (newsize < desiredsize)
209 static bool msgdone =
false;
213 LOG(VB_GENERAL, LOG_INFO,
LOC +
"RTP UDP socket receive buffer too small\n" +
214 QString(
"\tRTP UDP socket receive buffer size set to %1 but requested %2\n").arg(newsize).arg(desiredsize) +
215 QString(
"\tTo prevent UDP packet loss increase net.core.rmem_max e.g. with this command:\n") +
216 QString(
"\tsudo sysctl -w net.core.rmem_max=%1\n").arg(desiredsize) +
217 QString(
"\tand restart mythbackend."));
223 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"RTP UDP socket receive buffer size is %1").arg(newsize));
236 LOG(VB_RECORD, LOG_DEBUG,
LOC +
237 QString(
"dtor for %2").arg(
m_device));
244#ifdef DEBUG_PID_FILTERS
245 LOG(VB_RECORD, LOG_DEBUG,
LOC +
"UpdateFilters()");
258 pids.append(QString(
"%1").arg(it.key()));
260#ifdef DEBUG_PID_FILTERS
261 QString msg = QString(
"PIDS: '%1'").arg(pids.join(
","));
262 LOG(VB_RECORD, LOG_DEBUG,
LOC + msg);
268 QString pids_str = QString(
"pids=%1").arg(!pids.empty() ? pids.join(
",") :
"none");
269 LOG(VB_RECORD, LOG_INFO,
LOC +
"Play(pids_str) " + pids_str);
272 if (pids.size() > 32)
274 LOG(VB_RECORD, LOG_INFO,
LOC +
275 QString(
"Receive full TS, number of PIDs:%1 is more than 32").arg(pids.size()));
276 LOG(VB_RECORD, LOG_DEBUG,
LOC + pids_str);
277 pids_str = QString(
"pids=all");
293 LOG(VB_RECORD, LOG_INFO,
LOC +
"RunTS(): begin");
295 QElapsedTimer last_update;
316 last_update.restart();
321 auto elapsed = !last_update.isValid()
322 ? -1ms : std::chrono::milliseconds(last_update.elapsed());
323 elapsed = (elapsed < 0ms) ? 1s : elapsed;
328 last_update.restart();
332 std::this_thread::sleep_for(20ms);
335 LOG(VB_RECORD, LOG_INFO,
LOC +
"RunTS(): " +
"shutdown");
348 LOG(VB_RECORD, LOG_INFO,
LOC +
"RunTS(): end");
364 qry.append(QString(
"fe=%1").arg(
m_frontend+1));
366 qry.append(QString(
"sr=%1").arg(tuning.
m_symbolRate / 1000));
367 qry.append(
"msys=dvbc");
372 qry.append(QString(
"fe=%1").arg(
m_frontend+1));
383 qry.append(QString(
"fe=%1").arg(
m_frontend+1));
384 qry.append(QString(
"src=%1").arg(
m_satipsrc));
390 qry.append(QString(
"sr=%1").arg(tuning.
m_symbolRate / 1000));
392 qry.append(QString(
"plts=auto"));
401 url.setQuery(qry.join(
"&"));
405 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Tune url:%1").arg(url.toString()));
409 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Skip tuning, already tuned to this url"));
450 url.setScheme(
"rtsp");
455 QStringList devinfo =
m_device.split(
":");
456 if (devinfo.value(0).toUpper() ==
"UUID")
458 QString deviceId = QString(
"uuid:%1").arg(devinfo.value(1));
464 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Discovered device %1 at %2").arg(deviceId, ip));
468 LOG(VB_RECORD, LOG_ERR,
LOC + QString(
"Failed to discover device %1, no IP found").arg(deviceId));
522#define LOC_DRH QString("SH_DRH[%1]: ").arg(m_streamHandler->m_inputId)
525 : m_streamHandler(handler)
526 , m_socket(handler->m_dsocket)
529 QString(
"Starting data read helper for RTP UDP socket"));
532 connect(
m_socket, &QIODevice::readyRead,
541 LOG(VB_RECORD, LOG_DEBUG,
LOC_DRH + QString(
"Init flush count to %1").arg(
m_count));
546 LOG(VB_RECORD, LOG_INFO,
LOC_DRH + QString(
"%1").arg(__func__));
547 disconnect(
m_socket, &QIODevice::readyRead,
554 LOG(VB_RECORD, LOG_INFO, LOC_RH + QString(
"%1").arg(__func__));
559 while (
m_socket->hasPendingDatagrams())
562 LOG(VB_RECORD, LOG_INFO,
LOC_DRH + QString(
"%1 hasPendingDatagrams").arg(__func__));
565 quint16 senderPort = 0;
568 data.resize(
m_socket->pendingDatagramSize());
569 m_socket->readDatagram(data.data(), data.size(), &sender, &senderPort);
586 QString(
"Sequence number error -- Expected:%1 Received:%2")
593 LOG(VB_RECORD, LOG_INFO,
LOC_DRH + QString(
"Flushing RTP packet, %1 to do").arg(
m_count));
608 if (!streamDataList.isEmpty())
610 const unsigned char *data_buffer = ts_packet.
GetTSData();
613 for (
auto sit = streamDataList.cbegin(); sit != streamDataList.cend(); ++sit)
615 remainder = sit.key()->ProcessData(data_buffer, data_length);
625 QString(
"RTP data_length = %1 remainder = %2")
640#define LOC_CRH QString("SatIP_CRH[%1]: ").arg(m_streamHandler->m_inputId)
643 : m_streamHandler(handler)
644 , m_socket(handler->m_csocket)
647 QString(
"Starting read helper for RTCP UDP socket"));
650 connect(
m_socket, &QUdpSocket::readyRead,
656 LOG(VB_RECORD, LOG_INFO,
LOC_CRH + QString(
"%1").arg(__func__));
657 disconnect(
m_socket, &QIODevice::readyRead,
664 while (
m_socket->hasPendingDatagrams())
668 QString(
"Processing RTCP packet(pendingDatagramSize:%1)")
669 .arg(
m_socket->pendingDatagramSize()));
672 quint16 senderPort = 0;
674 QByteArray buf = QByteArray(
m_socket->pendingDatagramSize(), Qt::Uninitialized);
675 m_socket->readDatagram(buf.data(), buf.size(), &sender, &senderPort);
680 LOG(VB_GENERAL, LOG_ERR,
LOC_CRH +
"Invalid RTCP packet received");
684 QStringList data = pkt.
Data().split(
";");
689 LOG(VB_RECORD, LOG_DEBUG,
LOC_CRH + QString(
">2 %1 ").arg(__func__) + data.join(
'^'));
691 while (!found && i < data.length())
693 const QString& item = data.at(i);
695 if (item.startsWith(
"tuner="))
698 QStringList tuner = item.split(
",");
700 if (tuner.length() > 3)
702 int level = tuner.at(1).toInt();
703 bool lock = tuner.at(2).toInt() != 0;
704 int quality = tuner.at(3).toInt();
707 QString(
"Tuner lock:%1 level:%2 quality:%3").arg(lock).arg(level).arg(quality));
729 QVariant ss = socket->socketOption(QAbstractSocket::ReceiveBufferSizeSocketOption);
730 return ss.toUInt()/2;
745 if (rcvbuffersize > oldsize)
747 socket->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, rcvbuffersize);
DTVTransmitMode m_transMode
DTVModulation m_modulation
DTVModulationSystem m_modSys
DTVGuardInterval m_guardInterval
static const int kTunerTypeDVBS2
static const int kTunerTypeDVBT
static const int kTunerTypeDVBC
static const int kTunerTypeDVBS1
static const int kTunerTypeDVBT2
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
void setObjectName(const QString &name)
bool IsValid(void) const override
IsValid() must return true before any data access methods are called, other than GetDataReference() a...
uint GetPayloadType(void) const
uint GetSequenceNumber(void) const
RTP Transport Stream Data Packet.
unsigned int GetTSDataSize(void) const
const unsigned char * GetTSData(void) const
~SatIPControlReadHelper() override
SatIPStreamHandler * m_streamHandler
SatIPControlReadHelper(SatIPStreamHandler *handler)
SatIPDataReadHelper(SatIPStreamHandler *handler)
SatIPStreamHandler * m_streamHandler
~SatIPDataReadHelper() override
bool Setup(const QUrl &url, ushort clientPort1, ushort clientPort2)
bool Play(const QString &pids_str)
static QMutex s_handlersLock
SatIPControlReadHelper * m_controlReadHelper
SatIPDataReadHelper * m_dataReadHelper
SatIPStreamHandler(const QString &device, int inputid)
QRecursiveMutex m_tunelock
~SatIPStreamHandler() override
static uint GetUDPReceiveBufferSize(QUdpSocket *socket)
Get receive buffer size of UDP socket.
static SatIPStreamHandler * Get(const QString &devname, int inputid)
friend class SatIPDataReadHelper
static QMap< QString, SatIPStreamHandler * > s_handlers
void run(void) override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
bool UpdateFilters() override
static QMap< QString, uint > s_handlersRefCnt
static uint SetUDPReceiveBufferSize(QUdpSocket *socket, uint rcvbuffersize)
Set receive buffer size of UDP socket.
void SetSigmonValues(bool lock, int level)
bool Tune(const DTVMultiplex &tuning)
static void Return(SatIPStreamHandler *&ref, int inputid)
static QString freq(uint64_t freq)
static QString bw(DTVBandwidth bw)
static QString msys(DTVModulationSystem msys)
static int toTunerType(const QString &deviceid)
static QString tmode(DTVTransmitMode tmode)
static QString findDeviceIP(const QString &deviceuuid)
static QString ro(DTVRollOff ro)
static QString gi(DTVGuardInterval gi)
static QString mtype(DTVModulation mtype)
static QString pol(DTVPolarity pol)
static QString fec(DTVCodeRate fec)
QRecursiveMutex m_pidLock
StreamDataList m_streamDataList
void WriteMPTS(const unsigned char *buffer, uint len)
Write out a copy of the raw MPTS.
volatile bool m_runningDesired
bool RemoveAllPIDFilters(void)
void SetRunning(bool running, bool using_buffering, bool using_section_reader)
bool UpdateFiltersFromStreamData(void)
QRecursiveMutex m_listenerLock
QByteArray & GetDataReference(void)
#define LOG(_MASK_, _LEVEL_, _QSTRING_)