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  typedef enum FECType
19  {
24  } FECType;
25 
26  typedef enum IPTVType
27  {
28  kData = 1,
35  } IPTVType;
36 
37  typedef enum IPTVProtocol
38  {
39  inValid = 0,
40  udp,
41  rtp,
44  http_hls
45  } IPTVProtocol;
46 
47  IPTVTuningData() : m_fec_type(kNone), m_protocol(inValid)
48  {
49  memset(&m_bitrate, 0, sizeof(m_bitrate));
50  }
51 
52  IPTVTuningData(const QString &data_url, IPTVProtocol protocol) :
53  m_data_url(data_url), m_fec_type(kNone), 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_data_url(data_url),
63  m_fec_type(fec_type), m_fec_url0(fec_url0), m_fec_url1(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_data_url(data_url),
77  m_fec_type(kNone), m_fec_url0(fec_url0), m_fec_url1(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_fec_type = kRFC2733;
85  else if (fec_type.toLower() == "rfc5109")
86  m_fec_type = kRFC5109;
87  else if (fec_type.toLower() == "smpte2022")
88  m_fec_type = kSMPTE2022;
89  else
90  {
91  m_fec_url0.clear();
92  m_fec_url1.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_data_url = url;
130  GuessProtocol();
131  }
132 
133  QUrl GetDataURL(void) const { return m_data_url; }
134  QUrl GetFECURL0(void) const { return m_fec_url0; }
135  QUrl GetFECURL1(void) const { return m_fec_url1; }
136  QUrl GetURL(uint i) const
137  {
138  if (0 == i)
139  return GetDataURL();
140  else if (1 == i)
141  return GetFECURL0();
142  else if (2 == i)
143  return GetFECURL1();
144  else
145  return QUrl();
146  }
147  uint GetBitrate(uint i) const { return m_bitrate[i]; }
148 
149  FECType GetFECType(void) const { return m_fec_type; }
150 
151  QString GetFECTypeString(uint i) const
152  {
153  if (0 == i)
154  return "data";
155  switch (m_fec_type)
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  uint GetURLCount(void) const { return 3; }
166 
167  bool IsValid(void) const
168  {
169  bool ret = (m_data_url.isValid() && (IsUDP() || IsRTP() || IsRTSP() || IsHLS() || IsHTTPTS()));
170 
171  LOG(VB_CHANNEL, LOG_DEBUG, QString("IPTVTuningdata (%1): IsValid = %2")
172  .arg(m_data_url.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_data_url.isValid())
206  m_protocol = IPTVTuningData::inValid;
207  else if (m_data_url.scheme() == "udp")
208  m_protocol = IPTVTuningData::udp;
209  else if (m_data_url.scheme() == "rtp")
210  m_protocol = IPTVTuningData::rtp;
211  else if (m_data_url.scheme() == "rtsp")
212  m_protocol = IPTVTuningData::rtsp;
213  else if (((m_data_url.scheme() == "http") || (m_data_url.scheme() == "https")) && IsHLSPlaylist())
214  m_protocol = IPTVTuningData::http_hls;
215  else if ((m_data_url.scheme() == "http") || (m_data_url.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 (!qApp)
230  {
231  LOG(VB_GENERAL, LOG_ERR, QString("IsHLSPlaylist - No QApplication!!"));
232  return false;
233  }
234 
235  QString url = m_data_url.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:
271  uint m_bitrate[3];
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
unsigned int uint
Definition: compat.h:140
bool operator!=(const IPTVTuningData &other) const
bool IsUDP(void) const
QUrl GetFECURL0(void) const
QString GetFECTypeString(uint i) const
bool IsRTSP(void) const
uint GetURLCount(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
QUrl GetFECURL1(void) const
bool DownloadURL(const QUrl &url, QByteArray *buffer, uint timeout=30000, uint redirs=0, qint64 maxsize=0, QString *final_url=nullptr)
IPTVProtocol m_protocol
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