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