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  m_data_url(data_url),
76  m_fec_type(kNone), m_fec_url0(fec_url0), m_fec_url1(fec_url1)
77  {
78  GuessProtocol();
79  m_bitrate[0] = data_bitrate;
80  m_bitrate[1] = fec_bitrate0;
81  m_bitrate[2] = fec_bitrate1;
82  if (fec_type.toLower() == "rfc2733")
83  m_fec_type = kRFC2733;
84  else if (fec_type.toLower() == "rfc5109")
85  m_fec_type = kRFC5109;
86  else if (fec_type.toLower() == "smpte2022")
87  m_fec_type = kSMPTE2022;
88  else
89  {
90  m_fec_url0.clear();
91  m_fec_url1.clear();
92  }
93  }
94 
95  QString GetDeviceKey(void) const
96  {
97  const QUrl u = GetDataURL();
98  if (IsHLS())
99  return QString("%1(%2)").arg(u.toString()).arg(GetBitrate(0));
100  if (IsHTTPTS() || IsRTSP())
101  return QString("%1").arg(u.toString());
102  return QString("%1:%2:%3")
103  .arg(u.host()).arg(u.userInfo()).arg(u.port()).toLower();
104  }
105 
106  QString GetDeviceName(void) const
107  {
108  return QString("[data]%1[fectype]%2[fec0]%3[fec1]%4%5")
109  .arg(GetDataURL().toString())
110  .arg(GetFECTypeString(1))
111  .arg(GetFECURL1().toString())
112  .arg(GetFECURL1().toString())
113  .arg(GetBitrate(0) ? QString("-%1").arg(GetBitrate(0)) : "");
114  }
115 
116  bool operator==(const IPTVTuningData &other) const
117  {
118  return GetDeviceName() == other.GetDeviceName();
119  }
120 
121  bool operator!=(const IPTVTuningData &other) const
122  {
123  return GetDeviceName() != other.GetDeviceName();
124  }
125 
126  void SetDataURL(const QUrl &url)
127  {
128  m_data_url = url;
129  GuessProtocol();
130  }
131 
132  QUrl GetDataURL(void) const { return m_data_url; }
133  QUrl GetFECURL0(void) const { return m_fec_url0; }
134  QUrl GetFECURL1(void) const { return m_fec_url1; }
135  QUrl GetURL(uint i) const
136  {
137  if (0 == i)
138  return GetDataURL();
139  else if (1 == i)
140  return GetFECURL0();
141  else if (2 == i)
142  return GetFECURL1();
143  else
144  return QUrl();
145  }
146  uint GetBitrate(uint i) const { return m_bitrate[i]; }
147 
148  FECType GetFECType(void) const { return m_fec_type; }
149 
150  QString GetFECTypeString(uint i) const
151  {
152  if (0 == i)
153  return "data";
154  switch (m_fec_type)
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  uint GetURLCount(void) const { return 3; }
165 
166  bool IsValid(void) const
167  {
168  bool ret = (m_data_url.isValid() && (IsUDP() || IsRTP() || IsRTSP() || IsHLS() || IsHTTPTS()));
169 
170  LOG(VB_CHANNEL, LOG_DEBUG, QString("IPTVTuningdata (%1): IsValid = %2")
171  .arg(m_data_url.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_data_url.isValid())
205  m_protocol = IPTVTuningData::inValid;
206  else if (m_data_url.scheme() == "udp")
207  m_protocol = IPTVTuningData::udp;
208  else if (m_data_url.scheme() == "rtp")
209  m_protocol = IPTVTuningData::rtp;
210  else if (m_data_url.scheme() == "rtsp")
211  m_protocol = IPTVTuningData::rtsp;
212  else if (((m_data_url.scheme() == "http") || (m_data_url.scheme() == "https")) && IsHLSPlaylist())
213  m_protocol = IPTVTuningData::http_hls;
214  else if ((m_data_url.scheme() == "http") || (m_data_url.scheme() == "https"))
215  m_protocol = IPTVTuningData::http_ts;
216  else
217  m_protocol = IPTVTuningData::inValid;
218  }
219 
220  protected:
221  bool IsHLSPlaylist(void)
222  {
223  if (!qApp)
224  {
225  LOG(VB_GENERAL, LOG_ERR, QString("IsHLSPlaylist - No QApplication!!"));
226  return false;
227  }
228 
229  QString url = m_data_url.toString();
230 
231  // check url is valid for a playlist before downloading (see trac ticket #12856)
232  if(url.endsWith(".m3u8", Qt::CaseInsensitive) ||
233  url.endsWith(".m3u", Qt::CaseInsensitive))
234  {
235  LOG(VB_RECORD, LOG_INFO, QString("IsHLSPlaylist url ends with either .m3u8 or .m3u %1").arg(url));
236  }
237  else
238  {
239  // not a valid playlist so just return false
240  LOG(VB_RECORD, LOG_INFO, QString("IsHLSPlaylist url does not end with either .m3u8 or .m3u %1").arg(url));
241  return false;
242  }
243 
244  QByteArray buffer;
245 
246  MythSingleDownload downloader;
247  downloader.DownloadURL(url, &buffer, 5000, 0, 10000);
248  if (!buffer.size())
249  {
250  LOG(VB_GENERAL, LOG_ERR, QString("IsHLSPlaylist - Open Failed: %1\n\t\t\t%2")
251  .arg(downloader.ErrorString()).arg(url));
252  return false;
253  }
254 
255  QTextStream text(&buffer);
256  text.setCodec("UTF-8");
257  return (HLSReader::IsValidPlaylist(text));
258  }
259 
260  protected:
265  uint m_bitrate[3];
267 };
268 
269 #endif // _IPTV_TUNING_DATA_H_
FECType GetFECType(void) const
bool DownloadURL(const QUrl &url, QByteArray *buffer, uint timeout=30000, uint redirs=0, qint64 maxsize=0)
void GuessProtocol(void)
static bool IsValidPlaylist(QTextStream &text)
Definition: HLSReader.cpp:248
QUrl GetURL(uint i) const
QString toString(MarkTypes type)
bool IsValid(void) const
unsigned int uint
Definition: compat.h:140
bool IsHLSPlaylist(void)
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
IPTVProtocol m_protocol
QString GetDeviceName(void) const
QString ErrorString(void) const
IPTVTuningData(const QString &data_url, IPTVProtocol protocol)
QString GetDeviceKey(void) const
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)
bool IsHTTPTS() const
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
bool operator==(const IPTVTuningData &other) const
void SetDataURL(const QUrl &url)
bool IsRTP(void) const
QUrl GetDataURL(void) const