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));
246#ifdef DEBUG_PID_FILTERS
250 pids.append(QString(
"%1").arg(it.key()));
251 QString msg = QString(
"PIDS: '%1'").arg(pids.join(
","));
252 LOG(VB_RECORD, LOG_INFO,
LOC + msg);
275 pids.append(QString(
"%1").arg(it.key()));
282 LOG(VB_RECORD, LOG_INFO,
LOC +
283 QString(
"Number of PIDs used:%1 All PIDs:%2").arg(pids.size()).arg(
m_pidInfo.size()));
285 QString pids_str = QString(
"pids=%1").arg(!pids.empty() ? pids.join(
",") :
"none");
286 LOG(VB_RECORD, LOG_INFO,
LOC +
"Play(pids_str) " + pids_str);
289 if (pids.size() > 32)
291 LOG(VB_RECORD, LOG_INFO,
LOC +
292 QString(
"Receive full TS, number of PIDs:%1 is more than 32").arg(pids.size()));
293 LOG(VB_RECORD, LOG_DEBUG,
LOC + pids_str);
294 pids_str = QString(
"pids=all");
311 LOG(VB_RECORD, LOG_INFO,
LOC +
"RunTS(): begin");
313 QElapsedTimer last_update;
334 last_update.restart();
339 auto elapsed = !last_update.isValid()
340 ? -1ms : std::chrono::milliseconds(last_update.elapsed());
341 elapsed = (elapsed < 0ms) ? 1s : elapsed;
346 last_update.restart();
350 std::this_thread::sleep_for(20ms);
353 LOG(VB_RECORD, LOG_INFO,
LOC +
"RunTS(): " +
"shutdown");
366 LOG(VB_RECORD, LOG_INFO,
LOC +
"RunTS(): end");
382 qry.append(QString(
"fe=%1").arg(
m_frontend+1));
384 qry.append(QString(
"sr=%1").arg(tuning.
m_symbolRate / 1000));
385 qry.append(
"msys=dvbc");
390 qry.append(QString(
"fe=%1").arg(
m_frontend+1));
401 qry.append(QString(
"fe=%1").arg(
m_frontend+1));
402 qry.append(QString(
"src=%1").arg(
m_satipsrc));
408 qry.append(QString(
"sr=%1").arg(tuning.
m_symbolRate / 1000));
410 qry.append(QString(
"plts=auto"));
419 url.setQuery(qry.join(
"&"));
423 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Tune url:%1").arg(url.toString()));
427 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Skip tuning, already tuned to this url"));
468 url.setScheme(
"rtsp");
473 QStringList devinfo =
m_device.split(
":");
474 if (devinfo.value(0).toUpper() ==
"UUID")
476 QString deviceId = QString(
"uuid:%1").arg(devinfo.value(1));
482 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"Discovered device %1 at %2").arg(deviceId, ip));
486 LOG(VB_RECORD, LOG_ERR,
LOC + QString(
"Failed to discover device %1, no IP found").arg(deviceId));
540#define LOC_DRH QString("SH_DRH[%1]: ").arg(m_streamHandler->m_inputId)
543 : m_streamHandler(handler)
544 , m_socket(handler->m_dsocket)
547 QString(
"Starting data read helper for RTP UDP socket"));
550 connect(
m_socket, &QIODevice::readyRead,
559 LOG(VB_RECORD, LOG_DEBUG,
LOC_DRH + QString(
"Init flush count to %1").arg(
m_count));
564 LOG(VB_RECORD, LOG_INFO,
LOC_DRH + QString(
"%1").arg(__func__));
565 disconnect(
m_socket, &QIODevice::readyRead,
572 LOG(VB_RECORD, LOG_INFO, LOC_RH + QString(
"%1").arg(__func__));
577 while (
m_socket->hasPendingDatagrams())
580 LOG(VB_RECORD, LOG_INFO,
LOC_DRH + QString(
"%1 hasPendingDatagrams").arg(__func__));
583 quint16 senderPort = 0;
586 data.resize(
m_socket->pendingDatagramSize());
587 m_socket->readDatagram(data.data(), data.size(), &sender, &senderPort);
604 QString(
"Sequence number error -- Expected:%1 Received:%2")
611 LOG(VB_RECORD, LOG_INFO,
LOC_DRH + QString(
"Flushing RTP packet, %1 to do").arg(
m_count));
626 if (!streamDataList.isEmpty())
628 const unsigned char *data_buffer = ts_packet.
GetTSData();
631 for (
auto sit = streamDataList.cbegin(); sit != streamDataList.cend(); ++sit)
633 remainder = sit.key()->ProcessData(data_buffer, data_length);
643 QString(
"RTP data_length = %1 remainder = %2")
658#define LOC_CRH QString("SatIP_CRH[%1]: ").arg(m_streamHandler->m_inputId)
661 : m_streamHandler(handler)
662 , m_socket(handler->m_csocket)
665 QString(
"Starting read helper for RTCP UDP socket"));
668 connect(
m_socket, &QUdpSocket::readyRead,
674 LOG(VB_RECORD, LOG_INFO,
LOC_CRH + QString(
"%1").arg(__func__));
675 disconnect(
m_socket, &QIODevice::readyRead,
682 while (
m_socket->hasPendingDatagrams())
686 QString(
"Processing RTCP packet(pendingDatagramSize:%1)")
687 .arg(
m_socket->pendingDatagramSize()));
690 quint16 senderPort = 0;
692 QByteArray buf = QByteArray(
m_socket->pendingDatagramSize(), Qt::Uninitialized);
693 m_socket->readDatagram(buf.data(), buf.size(), &sender, &senderPort);
698 LOG(VB_GENERAL, LOG_ERR,
LOC_CRH +
"Invalid RTCP packet received");
702 QStringList data = pkt.
Data().split(
";");
707 LOG(VB_RECORD, LOG_DEBUG,
LOC_CRH + QString(
">2 %1 ").arg(__func__) + data.join(
'^'));
709 while (!found && i < data.length())
711 const QString& item = data.at(i);
713 if (item.startsWith(
"tuner="))
716 QStringList tuner = item.split(
",");
718 if (tuner.length() > 3)
720 int level = tuner.at(1).toInt();
721 bool lock = tuner.at(2).toInt() != 0;
722 int quality = tuner.at(3).toInt();
725 QString(
"Tuner lock:%1 level:%2 quality:%3").arg(lock).arg(level).arg(quality));
747 QVariant ss = socket->socketOption(QAbstractSocket::ReceiveBufferSizeSocketOption);
748 return ss.toUInt()/2;
763 if (rcvbuffersize > oldsize)
765 socket->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, rcvbuffersize);
770#include "moc_satipstreamhandler.cpp"
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)
PIDPriority GetPIDPriority(uint pid) const
QRecursiveMutex m_listenerLock
QByteArray & GetDataReference(void)
#define LOG(_MASK_, _LEVEL_, _QSTRING_)