3#include <QRegularExpression>
7#include "libmythbase/mythconfig.h"
13 static const QRegularExpression
kQuotes{
"^\"|\"$"};
17 QByteArray ba = uri.toLatin1();
18 QUrl url = QUrl::fromEncoded(ba);
19 return url.toString();
22 QString
RelativeURI(
const QString& surl,
const QString& spath)
24 QUrl url = QUrl(surl);
25 QUrl path = QUrl(spath);
27 if (!path.isRelative())
30 return url.resolved(path).toString();
35 int p = line.indexOf(QLatin1String(
":"));
39 QStringList list = line.mid(
p + 1).split(
',');
40 for (
const auto & it : std::as_const(list))
42 QString arg = it.trimmed();
43 if (arg.startsWith(attr))
45 int pos = arg.indexOf(QLatin1String(
"="));
48 return arg.mid(pos+1);
60 int p = line.indexOf(QLatin1String(
":"));
64 for ( ; i < line.size(); i++)
65 if (!line[i].isNumber())
69 target = line.mid(
p + 1, i -
p - 1).toInt();
79 int p = line.indexOf(QLatin1String(
":"));
83 for ( ; i < line.size(); i++)
84 if (!line[i].isNumber())
88 target = line.mid(
p + 1, i -
p - 1).toInt();
108 LOG(VB_RECORD, LOG_ERR, loc +
109 "#EXT-X-VERSION: no protocol version found, should be version 1.");
114 if (version < 1 || version > 7)
116 LOG(VB_RECORD, LOG_ERR, loc +
117 QString(
"#EXT-X-VERSION is %1, but we only understand 1 to 7")
135 LOG(VB_RECORD, LOG_INFO, loc +
136 QString(
"Parsing stream from %1").arg(url));
150 LOG(VB_RECORD, LOG_INFO, loc +
151 "#EXT-X-STREAM-INF: No PROGRAM-ID=<value>, using 1");
162 LOG(VB_RECORD, LOG_ERR, loc +
163 "#EXT-X-STREAM-INF: expected BANDWIDTH=<value>");
166 bandwidth = attr.toInt();
170 LOG(VB_RECORD, LOG_ERR, loc +
171 "#EXT-X-STREAM-INF: bandwidth cannot be 0");
185 if (!audio.isEmpty())
188 LOG(VB_RECORD, LOG_INFO, loc +
189 QString(
"#EXT-X-STREAM-INF: attribute AUDIO=%1").arg(audio));
194 if (!video.isEmpty())
197 LOG(VB_RECORD, LOG_INFO, loc +
198 QString(
"#EXT-X-STREAM-INF: attribute VIDEO=%1").arg(video));
202 LOG(VB_RECORD, LOG_INFO, loc +
203 QString(
"bandwidth adaptation detected (program-id=%1, bandwidth=%2)")
204 .arg(
id).arg(bandwidth));
218 LOG(VB_RECORD, LOG_INFO, loc + QString(
"Parsing EXT-X-MEDIA line"));
244 LOG(VB_RECORD, LOG_ERR, loc +
"expected #EXT-X-TARGETDURATION:<s>");
252 int& duration, QString& title,
269 int p = line.indexOf(QLatin1String(
":"));
272 LOG(VB_RECORD, LOG_ERR, loc +
273 QString(
"ParseSegmentInformation: Missing ':' in '%1'")
278 QStringList list = line.mid(
p + 1).split(
',');
283 LOG(VB_RECORD, LOG_ERR, loc +
284 QString(
"ParseSegmentInformation: Missing arguments in '%1'")
291 const QString& val = list[0];
294 int duration_seconds = val.toInt(&ok);
297 duration = duration_seconds * 1000;
301 LOG(VB_RECORD, LOG_ERR, loc +
302 QString(
"ParseSegmentInformation: invalid duration in '%1'")
309 double d = val.toDouble(&ok);
312 LOG(VB_RECORD, LOG_ERR, loc +
313 QString(
"ParseSegmentInformation: invalid duration in '%1'")
317 duration =
static_cast<int>(
d * 1000);
320 if (list.size() >= 2)
330 const QString& line,
const QString& loc)
343 LOG(VB_RECORD, LOG_ERR, loc +
"expected #EXT-X-MEDIA-SEQUENCE:<s>");
351 [[maybe_unused]]
bool& aesmsg,
352 const QString& loc, QString &path, QString &iv)
367 LOG(VB_RECORD, LOG_ERR, loc +
"#EXT-X-KEY: expected METHOD=<value>");
371 if (attr.startsWith(QLatin1String(
"NONE")))
376 LOG(VB_RECORD, LOG_ERR, loc +
"#EXT-X-KEY: URI not expected");
383 if (!parsed_iv.isEmpty())
385 LOG(VB_RECORD, LOG_ERR, loc +
"#EXT-X-KEY: IV not expected");
391 else if (attr.startsWith(QLatin1String(
"AES-128")))
396 LOG(VB_RECORD, LOG_INFO, loc +
397 "playback of AES-128 encrypted HTTP Live media detected.");
403 LOG(VB_RECORD, LOG_ERR, loc +
"#EXT-X-KEY: URI not found for "
404 "encrypted HTTP Live media in AES-128");
409 path =
DecodedURI(uri.remove(QChar(QLatin1Char(
'"'))));
412 LOG(VB_RECORD, LOG_DEBUG, QString(
"M3U::ParseKey #EXT-X-KEY: %1").arg(line));
413 LOG(VB_RECORD, LOG_DEBUG, QString(
"M3U::ParseKey path:%1 IV:%2").arg(path, iv));
415 else if (attr.startsWith(QLatin1String(
"SAMPLE-AES")))
417 LOG(VB_RECORD, LOG_ERR, loc +
"encryption SAMPLE-AES not supported.");
423 LOG(VB_RECORD, LOG_ERR, loc +
424 "invalid encryption type, only NONE "
426 "and AES-128 are supported"
459 LOG(VB_RECORD, LOG_ERR, loc +
460 QString(
"Attribute URI not present in: #EXT-X-MAP %1")
473 int p = line.indexOf(QLatin1String(
":"));
476 LOG(VB_RECORD, LOG_ERR, loc +
477 QString(
"ParseProgramDateTime: Missing ':' in '%1'")
482 QString dt_string = line.mid(
p+1);
501 int pos = line.indexOf(QLatin1String(
":"));
504 LOG(VB_RECORD, LOG_ERR, loc +
505 QString(
"ParseAllowCache: missing ':' in '%1'")
509 QString answer = line.mid(pos+1, 3);
510 if (answer.size() < 2)
512 LOG(VB_RECORD, LOG_ERR, loc +
"#EXT-X-ALLOW-CACHE, ignoring ...");
515 do_cache = (!answer.startsWith(QLatin1String(
"NO")));
535 LOG(VB_RECORD, LOG_ERR, loc +
"expected #EXT-X-DISCONTINUITY-SEQUENCE:<s>");
539 LOG(VB_RECORD, LOG_DEBUG, loc + QString(
"#EXT-X-DISCONTINUITY-SEQUENCE %1")
547 LOG(VB_RECORD, LOG_DEBUG, loc + QString(
"#EXT-X-DISCONTINUITY %1")
560 LOG(VB_RECORD, LOG_INFO, loc +
" video on demand (vod) mode");
578 LOG(VB_RECORD, LOG_DEBUG, loc + QString(
"#EXT-X-INDEPENDENT-SEGMENTS %1")
static const iso6937table * d
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
bool ParseDecimalValue(const QString &line, int &target)
Return the decimal argument in a line of type: blah:<decimal> presence of value <decimal> is compulso...
bool ParseDiscontinuitySequence(const QString &line, const QString &loc, int &discontinuity_sequence)
bool ParseVersion(const QString &line, const QString &loc, int &version)
bool ParseAllowCache(const QString &line, const QString &loc, bool &do_cache)
bool ParseEndList(const QString &loc, bool &is_vod)
bool ParseMap(const QString &line, const QString &loc, QString &uri)
QString RelativeURI(const QString &surl, const QString &spath)
bool ParseTargetDuration(const QString &line, const QString &loc, int &duration)
QString ParseAttributes(const QString &line, const char *attr)
bool ParseIndependentSegments(const QString &line, const QString &loc)
bool ParseMedia(const QString &line, const QString &loc, QString &media_type, QString &group_id, QString &uri, QString &name)
bool ParseMediaSequence(int64_t &sequence_num, const QString &line, const QString &loc)
bool ParseDiscontinuity(const QString &line, const QString &loc)
bool ParseProgramDateTime(const QString &line, const QString &loc, QDateTime &dt)
static const QRegularExpression kQuotes
bool ParseSegmentInformation(int version, const QString &line, int &duration, QString &title, const QString &loc)
QString DecodedURI(const QString &uri)
bool ParseKey(int version, const QString &line, bool &aesmsg, const QString &loc, QString &path, QString &iv)
bool ParseStreamInformation(const QString &line, const QString &url, const QString &loc, int &id, uint64_t &bandwidth, QString &audio, QString &video)
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.