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#ifdef DEBUG_PID_FILTERS
245 LOG(VB_RECORD, LOG_DEBUG, LOC + "UpdateFilters()");
246#endif // DEBUG_PID_FILTERS
247 QMutexLocker locker(&m_pidLock);
248
249 QStringList pids;
250
251 if (m_pidInfo.contains(0x2000))
252 {
253 pids.append("all");
254 }
255 else
256 {
257 for (auto it = m_pidInfo.cbegin(); it != m_pidInfo.cend(); ++it)
258 pids.append(QString("%1").arg(it.key()));
259 }
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
264
265 bool rval = true;
266 if (m_rtsp && m_oldpids != pids)
267 {
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);
270
271 // Telestar Digibit R1 Sat>IP box cannot handle a lot of pids
272 if (pids.size() > 32)
273 {
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");
278 }
279
280 rval = m_rtsp->Play(pids_str);
281 m_oldpids = pids;
282 }
283
284 return rval;
285}
286
288{
289 RunProlog();
290
291 SetRunning(true, false, false);
292
293 LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): begin");
294
295 QElapsedTimer last_update;
296
297 while (m_runningDesired && !m_bError)
298 {
299 {
300 QMutexLocker locker(&m_tunelock);
301
303 {
304 if (m_setupinvoked)
305 {
306 m_rtsp->Teardown();
307 m_setupinvoked = false;
308 }
309
311 {
313 m_setupinvoked = true;
314 }
315
316 last_update.restart();
317 }
318 }
319
320 // Update the PID filters every 100 milliseconds
321 auto elapsed = !last_update.isValid()
322 ? -1ms : std::chrono::milliseconds(last_update.elapsed());
323 elapsed = (elapsed < 0ms) ? 1s : elapsed;
324 if (elapsed > 100ms)
325 {
328 last_update.restart();
329 }
330
331 // Delay to avoid busy wait loop
332 std::this_thread::sleep_for(20ms);
333
334 }
335 LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): " + "shutdown");
336
338
339 // TEARDOWN command
340 if (m_setupinvoked)
341 {
342 QMutexLocker locker(&m_tunelock);
343 m_rtsp->Teardown();
344 m_setupinvoked = false;
345 m_oldtuningurl = "";
346 }
347
348 LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): end");
349 SetRunning(false, false, false);
350 RunEpilog();
351}
352
354{
355 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Tune %1").arg(tuning.m_frequency));
356
357 QMutexLocker locker(&m_tunelock);
358
359 // Build the query string
360 QStringList qry;
361
363 {
364 qry.append(QString("fe=%1").arg(m_frontend+1));
365 qry.append(QString("freq=%1").arg(SatIP::freq(tuning.m_frequency)));
366 qry.append(QString("sr=%1").arg(tuning.m_symbolRate / 1000)); // symbolrate in ksymb/s
367 qry.append("msys=dvbc");
368 qry.append(QString("mtype=%1").arg(SatIP::mtype(tuning.m_modulation)));
369 }
371 {
372 qry.append(QString("fe=%1").arg(m_frontend+1));
373 qry.append(QString("freq=%1").arg(SatIP::freq(tuning.m_frequency)));
374 qry.append(QString("bw=%1").arg(SatIP::bw(tuning.m_bandwidth)));
375 qry.append(QString("msys=%1").arg(SatIP::msys(tuning.m_modSys)));
376 qry.append(QString("tmode=%1").arg(SatIP::tmode(tuning.m_transMode)));
377 qry.append(QString("mtype=%1").arg(SatIP::mtype(tuning.m_modulation)));
378 qry.append(QString("gi=%1").arg(SatIP::gi(tuning.m_guardInterval)));
379 qry.append(QString("fec=%1").arg(SatIP::fec(tuning.m_fec)));
380 }
382 {
383 qry.append(QString("fe=%1").arg(m_frontend+1));
384 qry.append(QString("src=%1").arg(m_satipsrc));
385 qry.append(QString("freq=%1").arg(SatIP::freq(tuning.m_frequency*1000))); // frequency in Hz
386 qry.append(QString("pol=%1").arg(SatIP::pol(tuning.m_polarity)));
387 qry.append(QString("ro=%1").arg(SatIP::ro(tuning.m_rolloff)));
388 qry.append(QString("msys=%1").arg(SatIP::msys(tuning.m_modSys)));
389 qry.append(QString("mtype=%1").arg(SatIP::mtype(tuning.m_modulation)));
390 qry.append(QString("sr=%1").arg(tuning.m_symbolRate / 1000)); // symbolrate in ksymb/s
391 qry.append(QString("fec=%1").arg(SatIP::fec(tuning.m_fec)));
392 qry.append(QString("plts=auto")); // pilot tones
393 }
394 else
395 {
396 LOG(VB_RECORD, LOG_ERR, LOC + QString("Unhandled m_tunerType %1 %2").arg(m_tunerType).arg(m_tunerType.toString()));
397 return false;
398 }
399
400 QUrl url = QUrl(m_baseurl);
401 url.setQuery(qry.join("&"));
402
403 m_tuningurl = url;
404
405 LOG(VB_RECORD, LOG_INFO, LOC + QString("Tune url:%1").arg(url.toString()));
406
408 {
409 LOG(VB_RECORD, LOG_INFO, LOC + QString("Skip tuning, already tuned to this url"));
410 return true;
411 }
412
413 // Need SETUP and PLAY (with pids=none) to get RTSP packets with tuner lock info
414 if (m_rtsp)
415 {
416 bool rval = true;
417
418 // TEARDOWN command
419 if (m_setupinvoked)
420 {
421 rval = m_rtsp->Teardown();
422 m_setupinvoked = false;
423 }
424
425 // SETUP command
426 if (rval)
427 {
429 }
430 if (rval)
431 {
433 m_setupinvoked = true;
434 }
435
436 // PLAY command
437 if (rval)
438 {
439 m_rtsp->Play("pids=none");
440 m_oldpids = QStringList();
441 }
442 return rval;
443 }
444 return true;
445}
446
448{
449 QUrl url;
450 url.setScheme("rtsp");
451 url.setPort(554);
452 url.setPath("/");
453
454 // Discover the device using SSDP
455 QStringList devinfo = m_device.split(":");
456 if (devinfo.value(0).toUpper() == "UUID")
457 {
458 QString deviceId = QString("uuid:%1").arg(devinfo.value(1));
459 m_frontend = devinfo.value(3).toUInt();
460
461 QString ip = SatIP::findDeviceIP(deviceId);
462 if (ip != nullptr)
463 {
464 LOG(VB_RECORD, LOG_INFO, LOC + QString("Discovered device %1 at %2").arg(deviceId, ip));
465 }
466 else
467 {
468 LOG(VB_RECORD, LOG_ERR, LOC + QString("Failed to discover device %1, no IP found").arg(deviceId));
469 return false;
470 }
471
472 url.setHost(ip);
473 }
474 else
475 {
476 // TODO: Handling of manual IP devices
477 }
478
480 m_baseurl = url;
481
482 return true;
483}
484
486{
487 delete m_rtsp;
488 m_rtsp = nullptr;
489 m_baseurl = nullptr;
490}
491
493{
494 QMutexLocker locker(&m_sigmonLock);
495 return m_hasLock;
496}
497
499{
500 QMutexLocker locker(&m_sigmonLock);
501 return m_signalStrength;
502}
503
504void SatIPStreamHandler::SetSigmonValues(bool lock, int level)
505{
506 QMutexLocker locker(&m_sigmonLock);
507 m_hasLock = lock;
508 m_signalStrength = level;
509}
510
511// === RTP DataReadHelper ===================================================
512//
513// Read RTP stream data from the UDP socket and store it in the packet buffer
514// and write the packets immediately to the listeners.
515//
516// TODO
517// This has to be created in a separate thread to achieve minimum
518// minimum latency and so to avoid overflow of the UDP input buffers.
519// N.B. Then also with the socket that is now in the streamhandler.
520// ---------------------------------------------------------------------------
521
522#define LOC_DRH QString("SH_DRH[%1]: ").arg(m_streamHandler->m_inputId)
523
525 : m_streamHandler(handler)
526 , m_socket(handler->m_dsocket)
527{
528 LOG(VB_RECORD, LOG_INFO, LOC_DRH +
529 QString("Starting data read helper for RTP UDP socket"));
530
531 // Call ReadPending when there are RTP data packets received on m_socket
532 connect(m_socket, &QIODevice::readyRead,
534
535 // Number of RTP packets to discard at start.
536 // This is to flush the RTP packets that might still be in transit
537 // from the previously tuned channel.
538 m_count = 3;
539 m_valid = false;
540
541 LOG(VB_RECORD, LOG_DEBUG, LOC_DRH + QString("Init flush count to %1").arg(m_count));
542}
543
545{
546 LOG(VB_RECORD, LOG_INFO, LOC_DRH + QString("%1").arg(__func__));
547 disconnect(m_socket, &QIODevice::readyRead,
549}
550
552{
553#if 0
554 LOG(VB_RECORD, LOG_INFO, LOC_RH + QString("%1").arg(__func__));
555#endif
556
557 RTPDataPacket pkt;
558
559 while (m_socket->hasPendingDatagrams())
560 {
561#if 0
562 LOG(VB_RECORD, LOG_INFO, LOC_DRH + QString("%1 hasPendingDatagrams").arg(__func__));
563#endif
564 QHostAddress sender;
565 quint16 senderPort = 0;
566
567 QByteArray &data = pkt.GetDataReference();
568 data.resize(m_socket->pendingDatagramSize());
569 m_socket->readDatagram(data.data(), data.size(), &sender, &senderPort);
570
572 {
573 RTPTSDataPacket ts_packet(pkt);
574
575 if (!ts_packet.IsValid())
576 {
577 continue;
578 }
579
580 // Check the packet sequence number
581 uint expectedSequenceNumber = (m_sequenceNumber + 1) & 0xFFFF;
583 if ((expectedSequenceNumber != m_sequenceNumber) && m_valid)
584 {
585 LOG(VB_RECORD, LOG_ERR, LOC_DRH +
586 QString("Sequence number error -- Expected:%1 Received:%2")
587 .arg(expectedSequenceNumber).arg(m_sequenceNumber));
588 }
589
590 // Flush the first few packets after start
591 if (m_count > 0)
592 {
593 LOG(VB_RECORD, LOG_INFO, LOC_DRH + QString("Flushing RTP packet, %1 to do").arg(m_count));
594 m_count--;
595 }
596 else
597 {
598 m_valid = true;
599 }
600
601 // Send the packet data to all listeners
602 if (m_valid)
603 {
604 int remainder = 0;
605 {
606 QMutexLocker locker(&m_streamHandler->m_listenerLock);
607 auto streamDataList = m_streamHandler->m_streamDataList;
608 if (!streamDataList.isEmpty())
609 {
610 const unsigned char *data_buffer = ts_packet.GetTSData();
611 size_t data_length = ts_packet.GetTSDataSize();
612
613 for (auto sit = streamDataList.cbegin(); sit != streamDataList.cend(); ++sit)
614 {
615 remainder = sit.key()->ProcessData(data_buffer, data_length);
616 }
617
618 m_streamHandler->WriteMPTS(data_buffer, data_length - remainder);
619 }
620 }
621
622 if (remainder != 0)
623 {
624 LOG(VB_RECORD, LOG_INFO, LOC_DRH +
625 QString("RTP data_length = %1 remainder = %2")
626 .arg(ts_packet.GetTSDataSize()).arg(remainder));
627 }
628 }
629 }
630 }
631}
632
633
634// === RTSP RTCP ControlReadHelper ===========================================
635//
636// Read RTCP packets with control messages from the UDP socket.
637// Determine tuner state: lock and signal strength
638// ---------------------------------------------------------------------------
639
640#define LOC_CRH QString("SatIP_CRH[%1]: ").arg(m_streamHandler->m_inputId)
641
643 : m_streamHandler(handler)
644 , m_socket(handler->m_csocket)
645{
646 LOG(VB_RECORD, LOG_INFO, LOC_CRH +
647 QString("Starting read helper for RTCP UDP socket"));
648
649 // Call ReadPending when there is a message received on m_socket
650 connect(m_socket, &QUdpSocket::readyRead,
652}
653
655{
656 LOG(VB_RECORD, LOG_INFO, LOC_CRH + QString("%1").arg(__func__));
657 disconnect(m_socket, &QIODevice::readyRead,
659}
660
661// Process a RTCP packet received on m_socket
663{
664 while (m_socket->hasPendingDatagrams())
665 {
666#if 0
667 LOG(VB_RECORD, LOG_INFO, LOC_CRH +
668 QString("Processing RTCP packet(pendingDatagramSize:%1)")
669 .arg(m_socket->pendingDatagramSize()));
670#endif
671 QHostAddress sender;
672 quint16 senderPort = 0;
673
674 QByteArray buf = QByteArray(m_socket->pendingDatagramSize(), Qt::Uninitialized);
675 m_socket->readDatagram(buf.data(), buf.size(), &sender, &senderPort);
676
678 if (!pkt.IsValid())
679 {
680 LOG(VB_GENERAL, LOG_ERR, LOC_CRH + "Invalid RTCP packet received");
681 continue;
682 }
683
684 QStringList data = pkt.Data().split(";");
685 bool found = false;
686 int i = 0;
687
688#if 0
689 LOG(VB_RECORD, LOG_DEBUG, LOC_CRH + QString(">2 %1 ").arg(__func__) + data.join('^'));
690#endif
691 while (!found && i < data.length())
692 {
693 const QString& item = data.at(i);
694
695 if (item.startsWith("tuner="))
696 {
697 found = true;
698 QStringList tuner = item.split(",");
699
700 if (tuner.length() > 3)
701 {
702 int level = tuner.at(1).toInt(); // [0, 255]
703 bool lock = tuner.at(2).toInt() != 0; // [0 , 1]
704 int quality = tuner.at(3).toInt(); // [0, 15]
705
706 LOG(VB_RECORD, LOG_DEBUG, LOC_CRH +
707 QString("Tuner lock:%1 level:%2 quality:%3").arg(lock).arg(level).arg(quality));
708
709 m_streamHandler->SetSigmonValues(lock, level);
710 }
711 }
712 i++;
713 }
714 }
715}
716
717// ===========================================================================
718
728{
729 QVariant ss = socket->socketOption(QAbstractSocket::ReceiveBufferSizeSocketOption);
730 return ss.toUInt()/2;
731}
732
742uint SatIPStreamHandler::SetUDPReceiveBufferSize(QUdpSocket *socket, uint rcvbuffersize)
743{
745 if (rcvbuffersize > oldsize)
746 {
747 socket->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, rcvbuffersize);
748 }
750}
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:196
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:209
void setObjectName(const QString &name)
Definition: mthread.cpp:238
RTP Data Packet.
Definition: rtpdatapacket.h:33
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:58
uint GetSequenceNumber(void) const
Definition: rtpdatapacket.h:63
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:180
bool Play(const QString &pids_str)
Definition: satiprtsp.cpp:254
bool Teardown()
Definition: satiprtsp.cpp:272
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:270
static QString bw(DTVBandwidth bw)
Definition: satiputils.cpp:237
static QString msys(DTVModulationSystem msys)
Definition: satiputils.cpp:275
static int toTunerType(const QString &deviceid)
Definition: satiputils.cpp:203
static QString tmode(DTVTransmitMode tmode)
Definition: satiputils.cpp:334
static QString findDeviceIP(const QString &deviceuuid)
Definition: satiputils.cpp:154
static QString ro(DTVRollOff ro)
Definition: satiputils.cpp:441
static QString gi(DTVGuardInterval gi)
Definition: satiputils.cpp:363
static QString mtype(DTVModulation mtype)
Definition: satiputils.cpp:301
static QString pol(DTVPolarity pol)
Definition: satiputils.cpp:462
static QString fec(DTVCodeRate fec)
Definition: satiputils.cpp:396
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)
QRecursiveMutex m_listenerLock
QByteArray & GetDataReference(void)
Definition: udppacket.h:36
unsigned int uint
Definition: freesurround.h:24
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
#define LOC_DRH
#define LOC
#define LOC_CRH