MythTV master
satipstreamhandler.cpp
Go to the documentation of this file.
1// -*- Mode: c++ -*-
2
3// C++ headers
4#include <chrono>
5#include <thread>
6
7// Qt headers
8#include <QString>
9#include <QMap>
10#include <QMutex>
11#include <QMutexLocker>
12#include <QUdpSocket>
13
14// MythTV headers
16
17#include "cardutil.h"
18#include "dtvsignalmonitor.h"
19#include "rtp/rtptsdatapacket.h"
20#include "satiputils.h"
21#include "satipchannel.h"
22#include "satipstreamhandler.h"
23#include "satiprtcppacket.h"
24
25#define LOC QString("SatIPSH[%1]: ").arg(m_inputId)
26
27// For implementing Get & Return
28QMap<QString, SatIPStreamHandler*> SatIPStreamHandler::s_handlers;
29QMap<QString, uint> SatIPStreamHandler::s_handlersRefCnt;
31
32SatIPStreamHandler *SatIPStreamHandler::Get(const QString &devname, int inputid)
33{
34 QMutexLocker locker(&s_handlersLock);
35
36 QMap<QString, SatIPStreamHandler*>::iterator it = s_handlers.find(devname);
37
38 if (it == s_handlers.end())
39 {
40 auto *newhandler = new SatIPStreamHandler(devname, inputid);
41 newhandler->Open();
42 s_handlers[devname] = newhandler;
43 s_handlersRefCnt[devname] = 1;
44
45 LOG(VB_RECORD, LOG_INFO,
46 QString("SatIPSH[%1]: Creating new stream handler for %2")
47 .arg(inputid).arg(devname));
48 }
49 else
50 {
51 s_handlersRefCnt[devname]++;
52 uint rcount = s_handlersRefCnt[devname];
53 (*it)->m_inputId = inputid;
54
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));
58 }
59
60 return s_handlers[devname];
61}
62
64{
65 QMutexLocker locker(&s_handlersLock);
66
67 QString devname = ref->m_device;
68
69 QMap<QString, uint>::iterator rit = s_handlersRefCnt.find(devname);
70 if (rit == s_handlersRefCnt.end())
71 {
72 LOG(VB_RECORD, LOG_ERR, QString("SatIPSH[%1]: Return(%2) not found")
73 .arg(inputid).arg(devname));
74 return;
75 }
76
77 LOG(VB_RECORD, LOG_INFO, QString("SatIPSH[%1]: Return stream handler for %2 (%3 users)")
78 .arg(inputid).arg(devname).arg(*rit));
79
80 if (*rit > 1)
81 {
82 ref = nullptr;
83 (*rit)--;
84 return;
85 }
86
87 QMap<QString, SatIPStreamHandler*>::iterator it = s_handlers.find(devname);
88 if ((it != s_handlers.end()) && (*it == ref))
89 {
90 LOG(VB_RECORD, LOG_INFO, QString("SatIPSH[%1]: Closing handler for %2")
91 .arg(inputid).arg(devname));
92 (*it)->Stop();
93 (*it)->Close();
94 delete *it;
95 s_handlers.erase(it);
96 }
97 else
98 {
99 LOG(VB_GENERAL, LOG_ERR,
100 QString("SatIPSH[%1] Error: Couldn't find handler for %2")
101 .arg(inputid).arg(devname));
102 }
103
104 s_handlersRefCnt.erase(rit);
105 ref = nullptr;
106}
107
108SatIPStreamHandler::SatIPStreamHandler(const QString &device, int inputid)
109 : StreamHandler(device, inputid)
110 , m_inputId(inputid)
111 , m_device(device)
112{
113 setObjectName("SatIPStreamHandler");
114
115 LOG(VB_RECORD, LOG_DEBUG, LOC +
116 QString("ctor for %2").arg(device));
117
118 // Find the port to use for receiving the RTP data.
119 // First try a fixed even port number outside the range of dynamically allocated ports.
120 // If this fails try to get a dynamically allocated port.
121 uint preferred_port = 26420 + (2*inputid);
122 m_dsocket = new QUdpSocket(nullptr);
123 if (m_dsocket->bind(QHostAddress::AnyIPv4,
124 preferred_port,
125 QAbstractSocket::DefaultForPlatform))
126 {
127 m_dport = m_dsocket->localPort();
128 }
129 else
130 {
131 if (m_dsocket->bind(QHostAddress::AnyIPv4,
132 0,
133 QAbstractSocket::DefaultForPlatform))
134 {
135 m_dport = m_dsocket->localPort();
136 }
137 }
138
139 // Messages
140 if (m_dport == preferred_port)
141 {
142 LOG(VB_GENERAL, LOG_INFO, LOC +
143 QString("RTP socket bound to requested port %1").arg(m_dport));
144 }
145 else if (m_dport > 0)
146 {
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));
150 }
151 else
152 {
153 LOG(VB_GENERAL, LOG_ERR, LOC +
154 QString("Failed to bind RTP socket"));
155 return;
156 }
157
158 // ------------------------------------------------------------------------
159
160 // Control socket is next higher port; if we cannot bind do this port
161 // then try to bind to a port from the dynamic range
162 preferred_port = m_dport + 1;
163 m_csocket = new QUdpSocket(nullptr);
164
165 if (m_csocket->bind(QHostAddress::AnyIPv4,
166 preferred_port,
167 QAbstractSocket::DefaultForPlatform))
168 {
169 m_cport = m_csocket->localPort();
170 }
171 else
172 {
173 if (m_csocket->bind(QHostAddress::AnyIPv4,
174 0,
175 QAbstractSocket::DefaultForPlatform))
176 {
177 m_cport = m_csocket->localPort();
178 }
179 }
180
181 // Messages
182 if (m_cport == preferred_port)
183 {
184 LOG(VB_GENERAL, LOG_INFO, LOC +
185 QString("RTCP socket bound to requested port %1").arg(m_cport));
186 }
187 else if (m_cport > 0)
188 {
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));
192 }
193 else
194 {
195 LOG(VB_GENERAL, LOG_ERR, LOC +
196 QString("Failed to bind RTCP socket"));
197 }
198
199 // If the second port is not one more than the first port we are violating the SatIP standard.
200 // Possibly we should then redo the complete port binding.
201
202 // Increase receive packet buffer size for the RTP data stream to prevent packet loss
203 // Set UDP socket buffer size big enough to avoid buffer overrun.
204 // Buffer size can be reduced if and when the readhelper is running on a separate thread.
205 const uint desiredsize = 8*1000*1000;
206 const uint newsize = SatIPStreamHandler::SetUDPReceiveBufferSize(m_dsocket, desiredsize);
207 if (newsize < desiredsize)
208 {
209 static bool msgdone = false;
210
211 if (!msgdone)
212 {
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."));
218 msgdone = true;
219 }
220 }
221 else
222 {
223 LOG(VB_RECORD, LOG_INFO, LOC + QString("RTP UDP socket receive buffer size is %1").arg(newsize));
224 }
225
226 // Create the read helpers
229
230 // Create the RTSP handler
232}
233
235{
236 LOG(VB_RECORD, LOG_DEBUG, LOC +
237 QString("dtor for %2").arg(m_device));
238 delete m_controlReadHelper;
239 delete m_dataReadHelper;
240}
241
243{
244 QMutexLocker locker(&m_pidLock);
245
246#ifdef DEBUG_PID_FILTERS
247 {
248 QStringList pids;
249 for (auto it = m_pidInfo.cbegin(); it != m_pidInfo.cend(); ++it)
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);
253 }
254#endif // DEBUG_PID_FILTERS
255
256 bool rval = true;
257 if (m_rtsp)
258 {
259 QStringList pids;
260 if (m_pidInfo.contains(0x2000))
261 {
262 pids.append("all");
263 }
264 else
265 {
266 // Create a list without the low priority PIDs.
267 // This filters out the PMT PIDs of the channels
268 // on this multiplex that we do not want to receive.
269 for (auto it = m_pidInfo.cbegin(); it != m_pidInfo.cend(); ++it)
270 {
271 auto pid_priority = GetPIDPriority(it.key());
272 if (pid_priority == kPIDPriorityNormal ||
273 pid_priority == kPIDPriorityHigh)
274 {
275 pids.append(QString("%1").arg(it.key()));
276 }
277 }
278 }
279
280 if (m_oldpids != pids)
281 {
282 LOG(VB_RECORD, LOG_INFO, LOC +
283 QString("Number of PIDs used:%1 All PIDs:%2").arg(pids.size()).arg(m_pidInfo.size()));
284
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);
287
288 // Telestar Digibit R1 Sat>IP box cannot handle a lot of pids
289 if (pids.size() > 32)
290 {
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");
295 }
296
297 rval = m_rtsp->Play(pids_str);
298 m_oldpids = pids;
299 }
300 }
301
302 return rval;
303}
304
306{
307 RunProlog();
308
309 SetRunning(true, false, false);
310
311 LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): begin");
312
313 QElapsedTimer last_update;
314
315 while (m_runningDesired && !m_bError)
316 {
317 {
318 QMutexLocker locker(&m_tunelock);
319
321 {
322 if (m_setupinvoked)
323 {
324 m_rtsp->Teardown();
325 m_setupinvoked = false;
326 }
327
329 {
331 m_setupinvoked = true;
332 }
333
334 last_update.restart();
335 }
336 }
337
338 // Update the PID filters every 100 milliseconds
339 auto elapsed = !last_update.isValid()
340 ? -1ms : std::chrono::milliseconds(last_update.elapsed());
341 elapsed = (elapsed < 0ms) ? 1s : elapsed;
342 if (elapsed > 100ms)
343 {
346 last_update.restart();
347 }
348
349 // Delay to avoid busy wait loop
350 std::this_thread::sleep_for(20ms);
351
352 }
353 LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): " + "shutdown");
354
356
357 // TEARDOWN command
358 if (m_setupinvoked)
359 {
360 QMutexLocker locker(&m_tunelock);
361 m_rtsp->Teardown();
362 m_setupinvoked = false;
363 m_oldtuningurl = QUrl();
364 }
365
366 LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): end");
367 SetRunning(false, false, false);
368 RunEpilog();
369}
370
372{
373 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Tune %1").arg(tuning.m_frequency));
374
375 QMutexLocker locker(&m_tunelock);
376
377 // Build the query string
378 QStringList qry;
379
381 {
382 qry.append(QString("fe=%1").arg(m_frontend+1));
383 qry.append(QString("freq=%1").arg(SatIP::freq(tuning.m_frequency)));
384 qry.append(QString("sr=%1").arg(tuning.m_symbolRate / 1000)); // symbolrate in ksymb/s
385 qry.append("msys=dvbc");
386 qry.append(QString("mtype=%1").arg(SatIP::mtype(tuning.m_modulation)));
387 }
389 {
390 qry.append(QString("fe=%1").arg(m_frontend+1));
391 qry.append(QString("freq=%1").arg(SatIP::freq(tuning.m_frequency)));
392 qry.append(QString("bw=%1").arg(SatIP::bw(tuning.m_bandwidth)));
393 qry.append(QString("msys=%1").arg(SatIP::msys(tuning.m_modSys)));
394 qry.append(QString("tmode=%1").arg(SatIP::tmode(tuning.m_transMode)));
395 qry.append(QString("mtype=%1").arg(SatIP::mtype(tuning.m_modulation)));
396 qry.append(QString("gi=%1").arg(SatIP::gi(tuning.m_guardInterval)));
397 qry.append(QString("fec=%1").arg(SatIP::fec(tuning.m_fec)));
398 }
400 {
401 qry.append(QString("fe=%1").arg(m_frontend+1));
402 qry.append(QString("src=%1").arg(m_satipsrc));
403 qry.append(QString("freq=%1").arg(SatIP::freq(tuning.m_frequency*1000))); // frequency in Hz
404 qry.append(QString("pol=%1").arg(SatIP::pol(tuning.m_polarity)));
405 qry.append(QString("ro=%1").arg(SatIP::ro(tuning.m_rolloff)));
406 qry.append(QString("msys=%1").arg(SatIP::msys(tuning.m_modSys)));
407 qry.append(QString("mtype=%1").arg(SatIP::mtype(tuning.m_modulation)));
408 qry.append(QString("sr=%1").arg(tuning.m_symbolRate / 1000)); // symbolrate in ksymb/s
409 qry.append(QString("fec=%1").arg(SatIP::fec(tuning.m_fec)));
410 qry.append(QString("plts=auto")); // pilot tones
411 }
412 else
413 {
414 LOG(VB_RECORD, LOG_ERR, LOC + QString("Unhandled m_tunerType %1 %2").arg(m_tunerType.toInt()).arg(m_tunerType.toString()));
415 return false;
416 }
417
418 QUrl url = QUrl(m_baseurl);
419 url.setQuery(qry.join("&"));
420
421 m_tuningurl = url;
422
423 LOG(VB_RECORD, LOG_INFO, LOC + QString("Tune url:%1").arg(url.toString()));
424
426 {
427 LOG(VB_RECORD, LOG_INFO, LOC + QString("Skip tuning, already tuned to this url"));
428 return true;
429 }
430
431 // Need SETUP and PLAY (with pids=none) to get RTSP packets with tuner lock info
432 if (m_rtsp)
433 {
434 bool rval = true;
435
436 // TEARDOWN command
437 if (m_setupinvoked)
438 {
439 rval = m_rtsp->Teardown();
440 m_setupinvoked = false;
441 }
442
443 // SETUP command
444 if (rval)
445 {
447 }
448 if (rval)
449 {
451 m_setupinvoked = true;
452 }
453
454 // PLAY command
455 if (rval)
456 {
457 m_rtsp->Play("pids=none");
458 m_oldpids = QStringList();
459 }
460 return rval;
461 }
462 return true;
463}
464
466{
467 QUrl url;
468 url.setScheme("rtsp");
469 url.setPort(554);
470 url.setPath("/");
471
472 // Discover the device using SSDP
473 QStringList devinfo = m_device.split(":");
474 if (devinfo.value(0).toUpper() == "UUID")
475 {
476 QString deviceId = QString("uuid:%1").arg(devinfo.value(1));
477 m_frontend = devinfo.value(3).toUInt();
478
479 QString ip = SatIP::findDeviceIP(deviceId);
480 if (ip != nullptr)
481 {
482 LOG(VB_RECORD, LOG_INFO, LOC + QString("Discovered device %1 at %2").arg(deviceId, ip));
483 }
484 else
485 {
486 LOG(VB_RECORD, LOG_ERR, LOC + QString("Failed to discover device %1, no IP found").arg(deviceId));
487 return false;
488 }
489
490 url.setHost(ip);
491 }
492 else
493 {
494 // TODO: Handling of manual IP devices
495 }
496
498 m_baseurl = url;
499
500 return true;
501}
502
504{
505 delete m_rtsp;
506 m_rtsp = nullptr;
507 m_baseurl = QUrl();
508}
509
511{
512 QMutexLocker locker(&m_sigmonLock);
513 return m_hasLock;
514}
515
517{
518 QMutexLocker locker(&m_sigmonLock);
519 return m_signalStrength;
520}
521
522void SatIPStreamHandler::SetSigmonValues(bool lock, int level)
523{
524 QMutexLocker locker(&m_sigmonLock);
525 m_hasLock = lock;
526 m_signalStrength = level;
527}
528
529// === RTP DataReadHelper ===================================================
530//
531// Read RTP stream data from the UDP socket and store it in the packet buffer
532// and write the packets immediately to the listeners.
533//
534// TODO
535// This has to be created in a separate thread to achieve minimum
536// minimum latency and so to avoid overflow of the UDP input buffers.
537// N.B. Then also with the socket that is now in the streamhandler.
538// ---------------------------------------------------------------------------
539
540#define LOC_DRH QString("SH_DRH[%1]: ").arg(m_streamHandler->m_inputId)
541
543 : m_streamHandler(handler)
544 , m_socket(handler->m_dsocket)
545{
546 LOG(VB_RECORD, LOG_INFO, LOC_DRH +
547 QString("Starting data read helper for RTP UDP socket"));
548
549 // Call ReadPending when there are RTP data packets received on m_socket
550 connect(m_socket, &QIODevice::readyRead,
552
553 // Number of RTP packets to discard at start.
554 // This is to flush the RTP packets that might still be in transit
555 // from the previously tuned channel.
556 m_count = 3;
557 m_valid = false;
558
559 LOG(VB_RECORD, LOG_DEBUG, LOC_DRH + QString("Init flush count to %1").arg(m_count));
560}
561
563{
564 LOG(VB_RECORD, LOG_INFO, LOC_DRH + QString("%1").arg(__func__));
565 disconnect(m_socket, &QIODevice::readyRead,
567}
568
570{
571#if 0
572 LOG(VB_RECORD, LOG_INFO, LOC_RH + QString("%1").arg(__func__));
573#endif
574
575 RTPDataPacket pkt;
576
577 while (m_socket->hasPendingDatagrams())
578 {
579#if 0
580 LOG(VB_RECORD, LOG_INFO, LOC_DRH + QString("%1 hasPendingDatagrams").arg(__func__));
581#endif
582 QHostAddress sender;
583 quint16 senderPort = 0;
584
585 QByteArray &data = pkt.GetDataReference();
586 data.resize(m_socket->pendingDatagramSize());
587 m_socket->readDatagram(data.data(), data.size(), &sender, &senderPort);
588
590 {
591 RTPTSDataPacket ts_packet(pkt);
592
593 if (!ts_packet.IsValid())
594 {
595 continue;
596 }
597
598 // Check the packet sequence number
599 uint expectedSequenceNumber = (m_sequenceNumber + 1) & 0xFFFF;
601 if ((expectedSequenceNumber != m_sequenceNumber) && m_valid)
602 {
603 LOG(VB_RECORD, LOG_ERR, LOC_DRH +
604 QString("Sequence number error -- Expected:%1 Received:%2")
605 .arg(expectedSequenceNumber).arg(m_sequenceNumber));
606 }
607
608 // Flush the first few packets after start
609 if (m_count > 0)
610 {
611 LOG(VB_RECORD, LOG_INFO, LOC_DRH + QString("Flushing RTP packet, %1 to do").arg(m_count));
612 m_count--;
613 }
614 else
615 {
616 m_valid = true;
617 }
618
619 // Send the packet data to all listeners
620 if (m_valid)
621 {
622 int remainder = 0;
623 {
624 QMutexLocker locker(&m_streamHandler->m_listenerLock);
625 auto streamDataList = m_streamHandler->m_streamDataList;
626 if (!streamDataList.isEmpty())
627 {
628 const unsigned char *data_buffer = ts_packet.GetTSData();
629 size_t data_length = ts_packet.GetTSDataSize();
630
631 for (auto sit = streamDataList.cbegin(); sit != streamDataList.cend(); ++sit)
632 {
633 remainder = sit.key()->ProcessData(data_buffer, data_length);
634 }
635
636 m_streamHandler->WriteMPTS(data_buffer, data_length - remainder);
637 }
638 }
639
640 if (remainder != 0)
641 {
642 LOG(VB_RECORD, LOG_INFO, LOC_DRH +
643 QString("RTP data_length = %1 remainder = %2")
644 .arg(ts_packet.GetTSDataSize()).arg(remainder));
645 }
646 }
647 }
648 }
649}
650
651
652// === RTSP RTCP ControlReadHelper ===========================================
653//
654// Read RTCP packets with control messages from the UDP socket.
655// Determine tuner state: lock and signal strength
656// ---------------------------------------------------------------------------
657
658#define LOC_CRH QString("SatIP_CRH[%1]: ").arg(m_streamHandler->m_inputId)
659
661 : m_streamHandler(handler)
662 , m_socket(handler->m_csocket)
663{
664 LOG(VB_RECORD, LOG_INFO, LOC_CRH +
665 QString("Starting read helper for RTCP UDP socket"));
666
667 // Call ReadPending when there is a message received on m_socket
668 connect(m_socket, &QUdpSocket::readyRead,
670}
671
673{
674 LOG(VB_RECORD, LOG_INFO, LOC_CRH + QString("%1").arg(__func__));
675 disconnect(m_socket, &QIODevice::readyRead,
677}
678
679// Process a RTCP packet received on m_socket
681{
682 while (m_socket->hasPendingDatagrams())
683 {
684#if 0
685 LOG(VB_RECORD, LOG_INFO, LOC_CRH +
686 QString("Processing RTCP packet(pendingDatagramSize:%1)")
687 .arg(m_socket->pendingDatagramSize()));
688#endif
689 QHostAddress sender;
690 quint16 senderPort = 0;
691
692 QByteArray buf = QByteArray(m_socket->pendingDatagramSize(), Qt::Uninitialized);
693 m_socket->readDatagram(buf.data(), buf.size(), &sender, &senderPort);
694
696 if (!pkt.IsValid())
697 {
698 LOG(VB_GENERAL, LOG_ERR, LOC_CRH + "Invalid RTCP packet received");
699 continue;
700 }
701
702 QStringList data = pkt.Data().split(";");
703 bool found = false;
704 int i = 0;
705
706#if 0
707 LOG(VB_RECORD, LOG_DEBUG, LOC_CRH + QString(">2 %1 ").arg(__func__) + data.join('^'));
708#endif
709 while (!found && i < data.length())
710 {
711 const QString& item = data.at(i);
712
713 if (item.startsWith("tuner="))
714 {
715 found = true;
716 QStringList tuner = item.split(",");
717
718 if (tuner.length() > 3)
719 {
720 int level = tuner.at(1).toInt(); // [0, 255]
721 bool lock = tuner.at(2).toInt() != 0; // [0 , 1]
722 int quality = tuner.at(3).toInt(); // [0, 15]
723
724 LOG(VB_RECORD, LOG_DEBUG, LOC_CRH +
725 QString("Tuner lock:%1 level:%2 quality:%3").arg(lock).arg(level).arg(quality));
726
727 m_streamHandler->SetSigmonValues(lock, level);
728 }
729 }
730 i++;
731 }
732 }
733}
734
735// ===========================================================================
736
746{
747 QVariant ss = socket->socketOption(QAbstractSocket::ReceiveBufferSizeSocketOption);
748 return ss.toUInt()/2;
749}
750
760uint SatIPStreamHandler::SetUDPReceiveBufferSize(QUdpSocket *socket, uint rcvbuffersize)
761{
763 if (rcvbuffersize > oldsize)
764 {
765 socket->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, rcvbuffersize);
766 }
768}
769
770#include "moc_satipstreamhandler.cpp"
DTVCodeRate m_fec
Definition: dtvmultiplex.h:105
uint64_t m_symbolRate
Definition: dtvmultiplex.h:95
DTVTransmitMode m_transMode
Definition: dtvmultiplex.h:101
DTVModulation m_modulation
Definition: dtvmultiplex.h:100
DTVModulationSystem m_modSys
Definition: dtvmultiplex.h:106
DTVRollOff m_rolloff
Definition: dtvmultiplex.h:107
DTVGuardInterval m_guardInterval
Definition: dtvmultiplex.h:102
DTVBandwidth m_bandwidth
Definition: dtvmultiplex.h:97
uint64_t m_frequency
Definition: dtvmultiplex.h:94
DTVPolarity m_polarity
Definition: dtvmultiplex.h:104
static const int kTunerTypeDVBS2
QString toString() const
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().
Definition: mthread.cpp:180
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:193
void setObjectName(const QString &name)
Definition: mthread.cpp:222
RTP Data Packet.
Definition: rtpdatapacket.h:32
bool IsValid(void) const override
IsValid() must return true before any data access methods are called, other than GetDataReference() a...
uint GetPayloadType(void) const
Definition: rtpdatapacket.h:57
uint GetSequenceNumber(void) const
Definition: rtpdatapacket.h:62
RTP Transport Stream Data Packet.
unsigned int GetTSDataSize(void) const
const unsigned char * GetTSData(void) const
SatIPStreamHandler * m_streamHandler
SatIPControlReadHelper(SatIPStreamHandler *handler)
SatIPDataReadHelper(SatIPStreamHandler *handler)
SatIPStreamHandler * m_streamHandler
QString Data() const
bool IsValid() const
-*- Mode: c++ -*-
Definition: satiprtsp.h:26
bool Setup(const QUrl &url, ushort clientPort1, ushort clientPort2)
Definition: satiprtsp.cpp:181
bool Play(const QString &pids_str)
Definition: satiprtsp.cpp:255
bool Teardown()
Definition: satiprtsp.cpp:273
static QMutex s_handlersLock
SatIPControlReadHelper * m_controlReadHelper
SatIPDataReadHelper * m_dataReadHelper
SatIPStreamHandler(const QString &device, int inputid)
QRecursiveMutex m_tunelock
DTVTunerType m_tunerType
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)
Definition: satiputils.cpp:271
static QString bw(DTVBandwidth bw)
Definition: satiputils.cpp:238
static QString msys(DTVModulationSystem msys)
Definition: satiputils.cpp:276
static int toTunerType(const QString &deviceid)
Definition: satiputils.cpp:204
static QString tmode(DTVTransmitMode tmode)
Definition: satiputils.cpp:335
static QString findDeviceIP(const QString &deviceuuid)
Definition: satiputils.cpp:155
static QString ro(DTVRollOff ro)
Definition: satiputils.cpp:442
static QString gi(DTVGuardInterval gi)
Definition: satiputils.cpp:364
static QString mtype(DTVModulation mtype)
Definition: satiputils.cpp:302
static QString pol(DTVPolarity pol)
Definition: satiputils.cpp:463
static QString fec(DTVCodeRate fec)
Definition: satiputils.cpp:397
QRecursiveMutex m_pidLock
StreamDataList m_streamDataList
void WriteMPTS(const unsigned char *buffer, uint len)
Write out a copy of the raw MPTS.
PIDInfoMap m_pidInfo
volatile bool m_runningDesired
volatile bool m_bError
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)
Definition: udppacket.h:36
unsigned int uint
Definition: compat.h:60
@ kPIDPriorityHigh
@ kPIDPriorityNormal
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
#define LOC_DRH
#define LOC
#define LOC_CRH