MythTV  master
iptvtuningdata.h
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 #ifndef IPTV_TUNING_DATA_H
3 #define IPTV_TUNING_DATA_H
4 
5 // Qt headers
6 #include <QApplication>
7 #include <QString>
8 #include <QUrl>
9 
10 // MythTV headers
11 #include "mythtvexp.h"
12 #include "mythlogging.h"
13 #include "mythsingledownload.h"
15 
17 {
18  public:
19  enum FECType
20  {
25  };
26 
27  enum IPTVType
28  {
29  kData = 1,
36  };
37 
39  {
40  inValid = 0,
41  udp,
42  rtp,
45  http_hls
46  };
47 
49  {
50  memset(&m_bitrate, 0, sizeof(m_bitrate));
51  }
52 
53  IPTVTuningData(const QString &data_url, IPTVProtocol protocol) :
54  m_dataUrl(data_url), m_protocol(protocol)
55  {
56  memset(&m_bitrate, 0, sizeof(m_bitrate));
57  }
58 
59  IPTVTuningData(const QString &data_url, uint data_bitrate,
60  const FECType fec_type,
61  const QString &fec_url0, uint fec_bitrate0,
62  const QString &fec_url1, uint fec_bitrate1) :
63  m_dataUrl(data_url),
64  m_fecType(fec_type), m_fecUrl0(fec_url0), m_fecUrl1(fec_url1)
65  {
66  GuessProtocol();
67  m_bitrate[0] = data_bitrate;
68  m_bitrate[1] = fec_bitrate0;
69  m_bitrate[2] = fec_bitrate1;
70  }
71 
72  IPTVTuningData(const QString &data_url, uint data_bitrate,
73  const QString &fec_type,
74  const QString &fec_url0, uint fec_bitrate0,
75  const QString &fec_url1, uint fec_bitrate1,
76  const IPTVProtocol protocol) :
77  m_dataUrl(data_url),
78  m_fecUrl0(fec_url0), m_fecUrl1(fec_url1),
79  m_protocol(protocol)
80  {
81  m_bitrate[0] = data_bitrate;
82  m_bitrate[1] = fec_bitrate0;
83  m_bitrate[2] = fec_bitrate1;
84  if (fec_type.toLower() == "rfc2733")
85  m_fecType = kRFC2733;
86  else if (fec_type.toLower() == "rfc5109")
87  m_fecType = kRFC5109;
88  else if (fec_type.toLower() == "smpte2022")
89  m_fecType = kSMPTE2022;
90  else
91  {
92  m_fecUrl0.clear();
93  m_fecUrl1.clear();
94  }
95  }
96 
97  QString GetDeviceKey(void) const
98  {
99  const QUrl u = GetDataURL();
100  if (IsHLS())
101  return QString("%1(%2)").arg(u.toString()).arg(GetBitrate(0));
102  if (IsHTTPTS() || IsRTSP())
103  return QString("%1").arg(u.toString());
104  return QString("%1:%2:%3")
105  .arg(u.host()).arg(u.userInfo()).arg(u.port()).toLower();
106  }
107 
108  QString GetDeviceName(void) const
109  {
110  return QString("[data]%1[fectype]%2[fec0]%3[fec1]%4%5")
111  .arg(GetDataURL().toString())
112  .arg(GetFECTypeString(1))
113  .arg(GetFECURL1().toString())
114  .arg(GetFECURL1().toString())
115  .arg(GetBitrate(0) ? QString("-%1").arg(GetBitrate(0)) : "");
116  }
117 
118  bool operator==(const IPTVTuningData &other) const
119  {
120  return GetDeviceName() == other.GetDeviceName();
121  }
122 
123  bool operator!=(const IPTVTuningData &other) const
124  {
125  return GetDeviceName() != other.GetDeviceName();
126  }
127 
128  void SetDataURL(const QUrl &url)
129  {
130  m_dataUrl = url;
131  GuessProtocol();
132  }
133 
134  QUrl GetDataURL(void) const { return m_dataUrl; }
135  QUrl GetFECURL0(void) const { return m_fecUrl0; }
136  QUrl GetFECURL1(void) const { return m_fecUrl1; }
137  QUrl GetURL(uint i) const
138  {
139  if (0 == i)
140  return GetDataURL();
141  if (1 == i)
142  return GetFECURL0();
143  if (2 == i)
144  return GetFECURL1();
145  return QUrl();
146  }
147  uint GetBitrate(uint i) const { return m_bitrate[i]; }
148 
149  FECType GetFECType(void) const { return m_fecType; }
150 
151  QString GetFECTypeString(uint i) const
152  {
153  if (0 == i)
154  return "data";
155  switch (m_fecType)
156  {
157  case kNone: return QString();
158  case kRFC2733: return QString("rfc2733-%1").arg(i);
159  case kRFC5109: return QString("rfc5109-%1").arg(i);
160  case kSMPTE2022: return QString("smpte2022-%1").arg(i);
161  }
162  return QString();
163  }
164 
165  static uint GetURLCount(void) { return 3; }
166 
167  bool IsValid(void) const
168  {
169  bool ret = (m_dataUrl.isValid() && (IsUDP() || IsRTP() || IsRTSP() || IsHLS() || IsHTTPTS()));
170 
171  LOG(VB_CHANNEL, LOG_DEBUG, QString("IPTVTuningdata (%1): IsValid = %2")
172  .arg(m_dataUrl.toString())
173  .arg(ret ? "true" : "false"));
174 
175  return ret;
176  }
177 
178  bool IsUDP(void) const
179  {
180  return (m_protocol == udp);
181  }
182 
183  bool IsRTP(void) const
184  {
185  return (m_protocol == rtp);
186  }
187 
188  bool IsRTSP(void) const
189  {
190  return (m_protocol == rtsp);
191  }
192 
193  bool IsHLS() const
194  {
195  return (m_protocol == http_hls);
196  }
197 
198  bool IsHTTPTS() const
199  {
200  return (m_protocol == http_ts);
201  }
202 
203  void GuessProtocol(void)
204  {
205  if (!m_dataUrl.isValid())
206  m_protocol = IPTVTuningData::inValid; // NOLINT(bugprone-branch-clone)
207  else if (m_dataUrl.scheme() == "udp")
208  m_protocol = IPTVTuningData::udp;
209  else if (m_dataUrl.scheme() == "rtp")
210  m_protocol = IPTVTuningData::rtp;
211  else if (m_dataUrl.scheme() == "rtsp")
212  m_protocol = IPTVTuningData::rtsp;
213  else if (((m_dataUrl.scheme() == "http") || (m_dataUrl.scheme() == "https")) && IsHLSPlaylist())
214  m_protocol = IPTVTuningData::http_hls;
215  else if ((m_dataUrl.scheme() == "http") || (m_dataUrl.scheme() == "https"))
216  m_protocol = IPTVTuningData::http_ts;
217  else
218  m_protocol = IPTVTuningData::inValid;
219  }
220 
222  {
223  return m_protocol;
224  }
225 
226  protected:
227  bool IsHLSPlaylist(void) const
228  {
229  if (QCoreApplication::instance() == nullptr)
230  {
231  LOG(VB_GENERAL, LOG_ERR, QString("IsHLSPlaylist - No QCoreApplication!!"));
232  return false;
233  }
234 
235  QString url = m_dataUrl.toString();
236 
237  // check url is valid for a playlist before downloading (see trac ticket #12856)
238  if(url.endsWith(".m3u8", Qt::CaseInsensitive) ||
239  url.endsWith(".m3u", Qt::CaseInsensitive))
240  {
241  LOG(VB_RECORD, LOG_INFO, QString("IsHLSPlaylist url ends with either .m3u8 or .m3u %1").arg(url));
242  }
243  else
244  {
245  // not a valid playlist so just return false
246  LOG(VB_RECORD, LOG_INFO, QString("IsHLSPlaylist url does not end with either .m3u8 or .m3u %1").arg(url));
247  return false;
248  }
249 
250  QByteArray buffer;
251 
252  MythSingleDownload downloader;
253  downloader.DownloadURL(url, &buffer, 5000, 0, 10000);
254  if (!buffer.size())
255  {
256  LOG(VB_GENERAL, LOG_ERR, QString("IsHLSPlaylist - Open Failed: %1\n\t\t\t%2")
257  .arg(downloader.ErrorString()).arg(url));
258  return false;
259  }
260 
261  QTextStream text(&buffer);
262  text.setCodec("UTF-8");
263  return (HLSReader::IsValidPlaylist(text));
264  }
265 
266  protected:
267  QUrl m_dataUrl;
268  FECType m_fecType {kNone};
269  QUrl m_fecUrl0;
270  QUrl m_fecUrl1;
271  uint m_bitrate[3] {};
272  IPTVProtocol m_protocol {inValid};
273 };
274 
275 #endif // IPTV_TUNING_DATA_H
FECType GetFECType(void) const
void GuessProtocol(void)
static bool IsValidPlaylist(QTextStream &text)
Definition: HLSReader.cpp:256
QUrl GetURL(uint i) const
QString toString(MarkTypes type)
bool IsValid(void) const
bool IsHLSPlaylist(void) const
bool operator!=(const IPTVTuningData &other) const
bool IsUDP(void) const
QUrl GetFECURL0(void) const
QString GetFECTypeString(uint i) const
bool IsRTSP(void) const
#define MTV_PUBLIC
Definition: mythtvexp.h:15
IPTVTuningData(const QString &data_url, uint data_bitrate, const FECType fec_type, const QString &fec_url0, uint fec_bitrate0, const QString &fec_url1, uint fec_bitrate1)
uint GetBitrate(uint i) const
bool IsHLS() const
static uint GetURLCount(void)
QUrl GetFECURL1(void) const
bool DownloadURL(const QUrl &url, QByteArray *buffer, uint timeout=30000, uint redirs=0, qint64 maxsize=0, QString *final_url=nullptr)
unsigned int uint
Definition: compat.h:140
IPTVTuningData(const QString &data_url, uint data_bitrate, const QString &fec_type, const QString &fec_url0, uint fec_bitrate0, const QString &fec_url1, uint fec_bitrate1, const IPTVProtocol protocol)
QString GetDeviceName(void) const
QString ErrorString(void) const
IPTVTuningData(const QString &data_url, IPTVProtocol protocol)
QString GetDeviceKey(void) const
bool IsHTTPTS() const
bool operator==(const IPTVTuningData &other) const
IPTVProtocol GetProtocol(void) const
void SetDataURL(const QUrl &url)
bool IsRTP(void) const
QUrl GetDataURL(void) const
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23