MythTV  master
iptvstreamhandler.cpp
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 
3 // System headers
4 #ifdef _WIN32
5 # include <ws2tcpip.h>
6 #else
7 # include <sys/types.h>
8 # include <sys/socket.h>
9 # include <netinet/in.h>
10 # include <netinet/ip.h>
11 #endif
12 
13 // Qt headers
14 #include <QUdpSocket>
15 #include <QByteArray>
16 #include <QHostInfo>
17 
18 // MythTV headers
20 
21 #include "cetonrtsp.h"
22 #include "iptvstreamhandler.h"
23 #include "rtp/rtcpdatapacket.h"
24 #include "rtp/rtpdatapacket.h"
25 #include "rtp/rtpfecpacket.h"
26 #include "rtp/rtppacketbuffer.h"
27 #include "rtp/rtptsdatapacket.h"
28 #include "rtp/udppacketbuffer.h"
29 
30 #define LOC QString("IPTVSH[%1](%2): ").arg(m_inputId).arg(m_device)
31 
32 QMap<QString,IPTVStreamHandler*> IPTVStreamHandler::s_iptvhandlers;
35 
37  int inputid)
38 {
39  QMutexLocker locker(&s_iptvhandlers_lock);
40 
41  QString devkey = tuning.GetDeviceKey();
42 
43  QMap<QString,IPTVStreamHandler*>::iterator it = s_iptvhandlers.find(devkey);
44 
45  if (it == s_iptvhandlers.end())
46  {
47  auto *newhandler = new IPTVStreamHandler(tuning, inputid);
48  newhandler->Start();
49  s_iptvhandlers[devkey] = newhandler;
50  s_iptvhandlers_refcnt[devkey] = 1;
51 
52  LOG(VB_RECORD, LOG_INFO,
53  QString("IPTVSH[%1]: Creating new stream handler %2 for %3")
54  .arg(QString::number(inputid), devkey, tuning.GetDeviceName()));
55  }
56  else
57  {
58  s_iptvhandlers_refcnt[devkey]++;
59  uint rcount = s_iptvhandlers_refcnt[devkey];
60  LOG(VB_RECORD, LOG_INFO,
61  QString("IPTVSH[%1]: Using existing stream handler %2 for %3")
62  .arg(QString::number(inputid), devkey, tuning.GetDeviceName()) +
63  QString(" (%1 in use)").arg(rcount));
64  }
65 
66  return s_iptvhandlers[devkey];
67 }
68 
69 void IPTVStreamHandler::Return(IPTVStreamHandler * & ref, int inputid)
70 {
71  QMutexLocker locker(&s_iptvhandlers_lock);
72 
73  QString devname = ref->m_device;
74 
75  QMap<QString,uint>::iterator rit = s_iptvhandlers_refcnt.find(devname);
76  if (rit == s_iptvhandlers_refcnt.end())
77  return;
78 
79  LOG(VB_RECORD, LOG_INFO, QString("IPTVSH[%1]: Return(%2) has %3 handlers")
80  .arg(QString::number(inputid), devname).arg(*rit));
81 
82  if (*rit > 1)
83  {
84  ref = nullptr;
85  (*rit)--;
86  return;
87  }
88 
89  QMap<QString,IPTVStreamHandler*>::iterator it = s_iptvhandlers.find(devname);
90  if ((it != s_iptvhandlers.end()) && (*it == ref))
91  {
92  LOG(VB_RECORD, LOG_INFO, QString("IPTVSH[%1]: Closing handler for %2")
93  .arg(QString::number(inputid), devname));
94  ref->Stop();
95  delete *it;
96  s_iptvhandlers.erase(it);
97  }
98  else
99  {
100  LOG(VB_GENERAL, LOG_ERR,
101  QString("IPTVSH[%1] Error: Couldn't find handler for %2")
102  .arg(QString::number(inputid), devname));
103  }
104 
105  s_iptvhandlers_refcnt.erase(rit);
106  ref = nullptr;
107 }
108 
110  : StreamHandler(tuning.GetDeviceKey(), inputid)
111  , m_tuning(tuning)
112 {
114 }
115 
117 {
118  RunProlog();
119 
120  LOG(VB_GENERAL, LOG_INFO, LOC + "run()");
121 
122  SetRunning(true, false, false);
123 
124  // TODO Error handling..
125 
126  // Setup
127  CetonRTSP *rtsp = nullptr;
128  IPTVTuningData tuning = m_tuning;
129  if(m_tuning.IsRTSP())
130  {
131  rtsp = new CetonRTSP(m_tuning.GetURL(0));
132 
133  // Check RTSP capabilities
134  QStringList options;
135  if (!(rtsp->GetOptions(options) && options.contains("DESCRIBE") &&
136  options.contains("SETUP") && options.contains("PLAY") &&
137  options.contains("TEARDOWN")))
138  {
139  LOG(VB_RECORD, LOG_ERR, LOC +
140  "RTSP interface did not support the necessary options");
141  delete rtsp;
142  SetRunning(false, false, false);
143  RunEpilog();
144  return;
145  }
146 
147  if (!rtsp->Describe())
148  {
149  LOG(VB_RECORD, LOG_ERR, LOC +
150  "RTSP Describe command failed");
151  delete rtsp;
152  SetRunning(false, false, false);
153  RunEpilog();
154  return;
155  }
156 
157  m_useRtpStreaming = true;
158 
159  QUrl urltuned = m_tuning.GetURL(0);
160  urltuned.setScheme("rtp");
161  urltuned.setPort(0);
162  tuning = IPTVTuningData(urltuned.toString(), 0, IPTVTuningData::kNone,
163  urltuned.toString(), 0, "", 0);
164  }
165 
166  bool error = false;
167 
168  int start_port = 0;
169  for (size_t i = 0; i < IPTV_SOCKET_COUNT; i++)
170  {
171  QUrl url = tuning.GetURL(i);
172  if (url.port() < 0)
173  continue;
174 
175  LOG(VB_RECORD, LOG_DEBUG, LOC +
176  QString("setting up url[%1]:%2").arg(i).arg(url.toString()));
177 
178  // always ensure we use consecutive port numbers
179  int port = start_port ? start_port + 1 : url.port();
180  QString host = url.host();
181  QHostAddress dest_addr(host);
182 
183  if (!host.isEmpty() && dest_addr.isNull())
184  {
185  // address is a hostname, attempts to resolve it
186  QHostInfo info = QHostInfo::fromName(host);
187  QList<QHostAddress> list = info.addresses();
188 
189  if (list.isEmpty())
190  {
191  LOG(VB_RECORD, LOG_ERR, LOC +
192  QString("Can't resolve hostname:'%1'").arg(host));
193  }
194  else
195  {
196  for (const auto & addr : std::as_const(list))
197  {
198  dest_addr = addr;
199  if (addr.protocol() == QAbstractSocket::IPv6Protocol)
200  {
201  // We prefer first IPv4
202  break;
203  }
204  }
205  LOG(VB_RECORD, LOG_DEBUG, LOC +
206  QString("resolved %1 as %2").arg(host, dest_addr.toString()));
207  }
208  }
209  bool ipv6 = dest_addr.protocol() == QAbstractSocket::IPv6Protocol;
210  bool is_multicast = ipv6 ?
211  dest_addr.isInSubnet(QHostAddress::parseSubnet("ff00::/8")) :
212  (dest_addr.toIPv4Address() & 0xf0000000) == 0xe0000000;
213 
214  m_sockets[i] = new QUdpSocket();
215  if (!is_multicast)
216  {
217  // this allow to filter incoming traffic, and make sure it's from
218  // the requested server
219  m_sender[i] = dest_addr;
220  }
222 
223  // we need to open the descriptor ourselves so we
224  // can set some socket options
225  int fd = socket(ipv6 ? AF_INET6 : AF_INET, SOCK_DGRAM, 0); // create IPv4 socket
226  if (fd < 0)
227  {
228  LOG(VB_GENERAL, LOG_ERR, LOC +
229  "Unable to create socket " + ENO);
230  continue;
231  }
232  int buf_size = 2 * 1024 * std::max(tuning.GetBitrate(i)/1000, 500U);
233  if (!tuning.GetBitrate(i))
234  buf_size = 2 * 1024 * 1024;
235  int err = setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
236  (char *)&buf_size, sizeof(buf_size));
237  if (err)
238  {
239  LOG(VB_GENERAL, LOG_INFO, LOC +
240  QString("Increasing buffer size to %1 failed")
241  .arg(buf_size) + ENO);
242  }
243 
244  m_sockets[i]->setSocketDescriptor(
245  fd, QAbstractSocket::UnconnectedState, QIODevice::ReadOnly);
246 
247  // we bind to destination address if it's a multicast address, or
248  // the local ones otherwise
249  if (!m_sockets[i]->bind(is_multicast ?
250  dest_addr :
251  (ipv6 ? QHostAddress::AnyIPv6 : QHostAddress::Any),
252  port))
253  {
254  LOG(VB_GENERAL, LOG_ERR, LOC + "Binding to port failed.");
255  error = true;
256  }
257  else
258  {
259  start_port = m_sockets[i]->localPort();
260  }
261 
262  if (is_multicast)
263  {
264  m_sockets[i]->joinMulticastGroup(dest_addr);
265  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Joining %1")
266  .arg(dest_addr.toString()));
267  }
268 
269  if (!is_multicast && rtsp && i == 1)
270  {
271  m_rtcpDest = dest_addr;
272  }
273  }
274 
275  if (!error)
276  {
277  if (m_tuning.IsRTP() || m_tuning.IsRTSP())
278  m_buffer = new RTPPacketBuffer(tuning.GetBitrate(0));
279  else
280  m_buffer = new UDPPacketBuffer(tuning.GetBitrate(0));
282  m_writeHelper->Start();
283  }
284 
285  if (!error && rtsp)
286  {
287  // Start Streaming
288  if (!rtsp->Setup(m_sockets[0]->localPort(), m_sockets[1]->localPort(),
290  !rtsp->Play())
291  {
292  LOG(VB_RECORD, LOG_ERR, LOC +
293  "Starting recording (RTP initialization failed). Aborting.");
294  error = true;
295  }
296  if (m_rtspRtcpPort > 0)
297  {
300  }
301  }
302 
303  if (!error)
304  {
305  // Enter event loop
306  exec();
307  }
308 
309  // Clean up
310  for (size_t i = 0; i < IPTV_SOCKET_COUNT; i++)
311  {
312  if (m_sockets[i])
313  {
314  delete m_sockets[i];
315  m_sockets[i] = nullptr;
316  delete m_readHelpers[i];
317  m_readHelpers[i] = nullptr;
318  }
319  }
320  delete m_buffer;
321  m_buffer = nullptr;
322  delete m_writeHelper;
323  m_writeHelper = nullptr;
324 
325  if (rtsp)
326  {
327  rtsp->Teardown();
328  delete rtsp;
329  }
330 
331  SetRunning(false, false, false);
332  RunEpilog();
333 }
334 
336  IPTVStreamHandler *p, QUdpSocket *s, uint stream) :
337  m_parent(p), m_socket(s), m_sender(p->m_sender[stream]),
338  m_stream(stream)
339 {
340  connect(m_socket, &QIODevice::readyRead,
342 }
343 
344 #define LOC_WH QString("IPTVSH(%1): ").arg(m_parent->m_device)
345 
347 {
348  QHostAddress sender;
349  quint16 senderPort = 0;
350  bool sender_null = m_sender.isNull();
351 
352  if (0 == m_stream)
353  {
354  while (m_socket->hasPendingDatagrams())
355  {
357  QByteArray &data = packet.GetDataReference();
358  data.resize(m_socket->pendingDatagramSize());
359  m_socket->readDatagram(data.data(), data.size(),
360  &sender, &senderPort);
361  if (sender_null || sender == m_sender)
362  {
363  m_parent->m_buffer->PushDataPacket(packet);
364  }
365  else
366  {
367  LOG(VB_RECORD, LOG_WARNING, LOC_WH +
368  QString("Received on socket(%1) %2 bytes from non expected "
369  "sender:%3 (expected:%4) ignoring")
370  .arg(m_stream).arg(data.size())
371  .arg(sender.toString(), m_sender.toString()));
372  }
373  }
374  }
375  else
376  {
377  while (m_socket->hasPendingDatagrams())
378  {
380  QByteArray &data = packet.GetDataReference();
381  data.resize(m_socket->pendingDatagramSize());
382  m_socket->readDatagram(data.data(), data.size(),
383  &sender, &senderPort);
384  if (sender_null || sender == m_sender)
385  {
386  m_parent->m_buffer->PushFECPacket(packet, m_stream - 1);
387  }
388  else
389  {
390  LOG(VB_RECORD, LOG_WARNING, LOC_WH +
391  QString("Received on socket(%1) %2 bytes from non expected "
392  "sender:%3 (expected:%4) ignoring")
393  .arg(m_stream).arg(data.size())
394  .arg(sender.toString(), m_sender.toString()));
395  }
396  }
397  }
398 }
399 
401 {
402  if (m_timer)
403  {
404  killTimer(m_timer);
405  }
406  if (m_timerRtcp)
407  {
408  killTimer(m_timerRtcp);
409  }
410  m_timer = 0;
411  m_timerRtcp = 0;
412  m_parent = nullptr;
413 }
414 
416 {
417  if (event->timerId() == m_timerRtcp)
418  {
419  SendRTCPReport();
420  return;
421  }
422 
424  return;
425 
426  while (!m_parent->m_useRtpStreaming)
427  {
429 
430  if (packet.GetDataReference().isEmpty())
431  break;
432 
433  int remainder = 0;
434  {
435  QMutexLocker locker(&m_parent->m_listenerLock);
436  QByteArray &data = packet.GetDataReference();
437  for (auto sit = m_parent->m_streamDataList.cbegin();
438  sit != m_parent->m_streamDataList.cend(); ++sit)
439  {
440  remainder = sit.key()->ProcessData(
441  reinterpret_cast<const unsigned char*>(data.data()),
442  data.size());
443  }
444  }
445 
446  if (remainder != 0)
447  {
448  LOG(VB_RECORD, LOG_INFO, LOC_WH +
449  QString("data_length = %1 remainder = %2")
450  .arg(packet.GetDataReference().size()).arg(remainder));
451  }
452 
453  m_parent->m_buffer->FreePacket(packet);
454  }
455 
456  while (m_parent->m_useRtpStreaming)
457  {
459 
460  if (!packet.IsValid())
461  break;
462 
464  {
465  RTPTSDataPacket ts_packet(packet);
466 
467  if (!ts_packet.IsValid())
468  {
469  m_parent->m_buffer->FreePacket(packet);
470  continue;
471  }
472 
473  uint exp_seq_num = m_lastSequenceNumber + 1;
474  uint seq_num = ts_packet.GetSequenceNumber();
475  if (m_lastSequenceNumber &&
476  ((exp_seq_num&0xFFFF) != (seq_num&0xFFFF)))
477  {
478  LOG(VB_RECORD, LOG_INFO, LOC_WH +
479  QString("Sequence number mismatch %1!=%2")
480  .arg(seq_num).arg(exp_seq_num));
481  if (seq_num > exp_seq_num)
482  {
483  m_lostInterval = seq_num - exp_seq_num;
485  }
486  }
487  m_lastSequenceNumber = seq_num;
488  m_lastTimestamp = ts_packet.GetTimeStamp();
489  LOG(VB_RECORD, LOG_DEBUG,
490  QString("Processing RTP packet(seq:%1 ts:%2)")
492 
493  m_parent->m_listenerLock.lock();
494 
495  int remainder = 0;
496  for (auto sit = m_parent->m_streamDataList.cbegin();
497  sit != m_parent->m_streamDataList.cend(); ++sit)
498  {
499  remainder = sit.key()->ProcessData(
500  ts_packet.GetTSData(), ts_packet.GetTSDataSize());
501  }
502 
503  m_parent->m_listenerLock.unlock();
504 
505  if (remainder != 0)
506  {
507  LOG(VB_RECORD, LOG_INFO, LOC_WH +
508  QString("data_length = %1 remainder = %2")
509  .arg(ts_packet.GetTSDataSize()).arg(remainder));
510  }
511  }
512  m_parent->m_buffer->FreePacket(packet);
513  }
514 }
515 
517 {
518  if (m_parent->m_rtcpDest.isNull())
519  {
520  // no point sending data if we don't know where to
521  return;
522  }
524  RTCPDataPacket rtcp =
528  QByteArray buf = rtcp.GetData();
529 
530  LOG(VB_RECORD, LOG_DEBUG, LOC_WH +
531  QString("Sending RTCPReport to %1:%2")
532  .arg(m_parent->m_rtcpDest.toString())
533  .arg(m_parent->m_rtspRtcpPort));
534  m_parent->m_sockets[1]->writeDatagram(buf.constData(), buf.size(),
538 }
IPTVStreamHandler::Return
static void Return(IPTVStreamHandler *&ref, int inputid)
Definition: iptvstreamhandler.cpp:69
MThread::exec
int exec(void)
Enters the qt event loop. call exit or quit to exit thread.
Definition: mthread.cpp:325
RTPDataPacket::GetTimeStamp
uint GetTimeStamp(void) const
Definition: rtpdatapacket.h:102
IPTVStreamHandler::run
void run(void) override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: iptvstreamhandler.cpp:116
IPTVStreamHandler::m_tuning
IPTVTuningData m_tuning
Definition: iptvstreamhandler.h:102
rtcpdatapacket.h
IPTVStreamHandlerReadHelper::m_parent
IPTVStreamHandler * m_parent
Definition: iptvstreamhandler.h:39
ENO
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:73
IPTVTuningData::IsRTSP
bool IsRTSP(void) const
Definition: iptvtuningdata.h:193
IPTVStreamHandlerReadHelper::m_sender
QHostAddress m_sender
Definition: iptvstreamhandler.h:41
IPTVStreamHandler::IPTVStreamHandler
IPTVStreamHandler(const IPTVTuningData &tuning, int inputid)
Definition: iptvstreamhandler.cpp:109
IPTVStreamHandler::m_rtspSsrc
uint32_t m_rtspSsrc
Definition: iptvstreamhandler.h:112
IPTVStreamHandler::m_readHelpers
std::array< IPTVStreamHandlerReadHelper *, IPTV_SOCKET_COUNT > m_readHelpers
Definition: iptvstreamhandler.h:104
error
static void error(const char *str,...)
Definition: vbi.cpp:36
IPTVStreamHandlerWriteHelper::Start
void Start(void)
Definition: iptvstreamhandler.h:54
IPTVStreamHandlerWriteHelper::~IPTVStreamHandlerWriteHelper
~IPTVStreamHandlerWriteHelper() override
Definition: iptvstreamhandler.cpp:400
rtpdatapacket.h
RTPTSDataPacket
RTP Transport Stream Data Packet.
Definition: rtptsdatapacket.h:16
StreamHandler::SetRunning
void SetRunning(bool running, bool using_buffering, bool using_section_reader)
Definition: streamhandler.cpp:173
IPTVStreamHandler::m_sockets
std::array< QUdpSocket *, IPTV_SOCKET_COUNT > m_sockets
Definition: iptvstreamhandler.h:103
PacketBuffer::FreePacket
void FreePacket(const UDPPacket &packet)
Frees an RTPDataPacket returned by PopDataPacket.
Definition: packetbuffer.cpp:49
StreamHandler::Stop
void Stop(void)
Definition: streamhandler.cpp:155
StreamHandler
Definition: streamhandler.h:56
RTPTSDataPacket::GetTSDataSize
unsigned int GetTSDataSize(void) const
Definition: rtptsdatapacket.h:29
IPTVStreamHandlerWriteHelper::StartRTCPRR
void StartRTCPRR(void)
Definition: iptvstreamhandler.h:58
CetonRTSP::Setup
bool Setup(ushort clientPort1, ushort clientPort2, ushort &rtpPort, ushort &rtcpPort, uint32_t &ssrc)
Definition: cetonrtsp.cpp:394
IPTVTuningData::kNone
@ kNone
Definition: iptvtuningdata.h:26
RTCPDataPacket::GetData
QByteArray GetData(void) const
Definition: rtcpdatapacket.h:57
IPTVStreamHandlerReadHelper::ReadPending
void ReadPending(void)
Definition: iptvstreamhandler.cpp:346
IPTVStreamHandlerWriteHelper::m_lastSequenceNumber
uint m_lastSequenceNumber
Definition: iptvstreamhandler.h:72
LOC_WH
#define LOC_WH
Definition: iptvstreamhandler.cpp:344
IPTVTuningData::IsRTP
bool IsRTP(void) const
Definition: iptvtuningdata.h:188
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MThread::RunProlog
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:196
IPTVStreamHandlerWriteHelper::timerEvent
void timerEvent(QTimerEvent *event) override
Definition: iptvstreamhandler.cpp:415
IPTVStreamHandlerReadHelper::m_stream
uint m_stream
Definition: iptvstreamhandler.h:42
IPTVStreamHandler::s_iptvhandlers
static QMap< QString, IPTVStreamHandler * > s_iptvhandlers
Definition: iptvstreamhandler.h:117
IPTVStreamHandlerWriteHelper::m_timerRtcp
int m_timerRtcp
Definition: iptvstreamhandler.h:71
IPTVStreamHandlerWriteHelper::m_lostInterval
int m_lostInterval
Definition: iptvstreamhandler.h:76
IPTVTuningData::GetDeviceKey
QString GetDeviceKey(void) const
Definition: iptvtuningdata.h:102
IPTVStreamHandlerWriteHelper::m_parent
IPTVStreamHandler * m_parent
Definition: iptvstreamhandler.h:69
IPTVStreamHandlerWriteHelper::m_previousLastSequenceNumber
uint m_previousLastSequenceNumber
Definition: iptvstreamhandler.h:74
IPTVStreamHandler::IPTVStreamHandlerWriteHelper
friend class IPTVStreamHandlerWriteHelper
Definition: iptvstreamhandler.h:82
StreamHandler::m_listenerLock
QRecursiveMutex m_listenerLock
Definition: streamhandler.h:144
mythlogging.h
IPTVStreamHandler::IPTVStreamHandlerReadHelper
friend class IPTVStreamHandlerReadHelper
Definition: iptvstreamhandler.h:81
RTCP_TIMER
static constexpr std::chrono::milliseconds RTCP_TIMER
Definition: iptvstreamhandler.h:20
hardwareprofile.config.p
p
Definition: config.py:33
CetonRTSP::Play
bool Play(void)
Definition: cetonrtsp.cpp:449
IPTVTuningData::GetDeviceName
QString GetDeviceName(void) const
Definition: iptvtuningdata.h:113
IPTVStreamHandler::s_iptvhandlers_refcnt
static QMap< QString, uint > s_iptvhandlers_refcnt
Definition: iptvstreamhandler.h:118
IPTVStreamHandler::m_useRtpStreaming
bool m_useRtpStreaming
Definition: iptvstreamhandler.h:109
IPTVStreamHandlerWriteHelper::m_lost
int m_lost
Definition: iptvstreamhandler.h:75
IPTVTuningData
Definition: iptvtuningdata.h:21
CetonRTSP::Teardown
bool Teardown(void)
Definition: cetonrtsp.cpp:457
MThread::RunEpilog
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:209
CetonRTSP::GetOptions
bool GetOptions(QStringList &options)
Definition: cetonrtsp.cpp:240
IPTVStreamHandler::Get
static IPTVStreamHandler * Get(const IPTVTuningData &tuning, int inputid)
Definition: iptvstreamhandler.cpp:36
IPTVStreamHandler::m_sender
std::array< QHostAddress, IPTV_SOCKET_COUNT > m_sender
Definition: iptvstreamhandler.h:105
RTPTSDataPacket::GetTSData
const unsigned char * GetTSData(void) const
Definition: rtptsdatapacket.h:24
uint
unsigned int uint
Definition: compat.h:81
rtppacketbuffer.h
RTPDataPacket::GetSequenceNumber
uint GetSequenceNumber(void) const
Definition: rtpdatapacket.h:97
LOC
#define LOC
Definition: iptvstreamhandler.cpp:30
IPTVStreamHandler::m_buffer
PacketBuffer * m_buffer
Definition: iptvstreamhandler.h:107
CetonRTSP::Describe
bool Describe(void)
Definition: cetonrtsp.cpp:323
udppacketbuffer.h
CetonRTSP
Definition: cetonrtsp.h:26
PacketBuffer::HasAvailablePacket
bool HasAvailablePacket(void) const
Returns true if there are ordered packets ready for processing.
Definition: packetbuffer.cpp:19
PacketBuffer::PushFECPacket
virtual void PushFECPacket(const UDPPacket &, unsigned int)=0
IPTV_SOCKET_COUNT
static constexpr size_t IPTV_SOCKET_COUNT
Definition: iptvstreamhandler.h:19
StreamHandler::m_streamDataList
StreamDataList m_streamDataList
Definition: streamhandler.h:145
PacketBuffer::PushDataPacket
virtual void PushDataPacket(const UDPPacket &)=0
RTPDataPacket::GetPayloadType
uint GetPayloadType(void) const
Definition: rtpdatapacket.h:92
IPTVStreamHandler::m_rtcpDest
QHostAddress m_rtcpDest
Definition: iptvstreamhandler.h:113
IPTVStreamHandler::m_rtspRtpPort
ushort m_rtspRtpPort
Definition: iptvstreamhandler.h:110
rtptsdatapacket.h
IPTVStreamHandlerWriteHelper::SendRTCPReport
void SendRTCPReport(void)
Definition: iptvstreamhandler.cpp:516
IPTVStreamHandler
Definition: iptvstreamhandler.h:79
IPTVStreamHandler::m_rtspRtcpPort
ushort m_rtspRtcpPort
Definition: iptvstreamhandler.h:111
RTPDataPacket
RTP Data Packet.
Definition: rtpdatapacket.h:32
IPTVStreamHandler::s_iptvhandlers_lock
static QMutex s_iptvhandlers_lock
Definition: iptvstreamhandler.h:116
IPTVStreamHandlerReadHelper::m_socket
QUdpSocket * m_socket
Definition: iptvstreamhandler.h:40
PacketBuffer::PopDataPacket
UDPPacket PopDataPacket(void)
Fetches a data packet for processing.
Definition: packetbuffer.cpp:24
UDPPacketBuffer
Definition: udppacketbuffer.h:12
iptvstreamhandler.h
RTCPDataPacket
RTCP Data Packet.
Definition: rtcpdatapacket.h:38
UDPPacket::GetDataReference
QByteArray & GetDataReference(void)
Definition: udppacket.h:36
RTPDataPacket::kPayLoadTypeTS
@ kPayLoadTypeTS
Definition: rtpdatapacket.h:88
RTPPacketBuffer
Definition: rtppacketbuffer.h:15
StreamHandler::m_device
QString m_device
Definition: streamhandler.h:111
IPTVStreamHandlerReadHelper::IPTVStreamHandlerReadHelper
IPTVStreamHandlerReadHelper(IPTVStreamHandler *p, QUdpSocket *s, uint stream)
Definition: iptvstreamhandler.cpp:335
IPTVTuningData::GetBitrate
uint GetBitrate(uint i) const
Definition: iptvtuningdata.h:152
build_compdb.options
options
Definition: build_compdb.py:11
UDPPacket
UDP Packet.
Definition: udppacket.h:20
rtpfecpacket.h
IPTVTuningData::GetURL
QUrl GetURL(uint i) const
Definition: iptvtuningdata.h:142
cetonrtsp.h
RTPDataPacket::IsValid
bool IsValid(void) const override
IsValid() must return true before any data access methods are called, other than GetDataReference() a...
Definition: rtpdatapacket.h:42
IPTVStreamHandler::m_writeHelper
IPTVStreamHandlerWriteHelper * m_writeHelper
Definition: iptvstreamhandler.h:106
IPTVStreamHandlerWriteHelper::m_timer
int m_timer
Definition: iptvstreamhandler.h:70
PacketBuffer::GetEmptyPacket
UDPPacket GetEmptyPacket(void)
Gets a packet for use in PushDataPacket/PushFECPacket.
Definition: packetbuffer.cpp:35
IPTVStreamHandlerWriteHelper::m_lastTimestamp
uint m_lastTimestamp
Definition: iptvstreamhandler.h:73