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()");
246 #endif // DEBUG_PID_FILTERS
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);
263 #endif // DEBUG_PID_FILTERS
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);