1 #include <QRegularExpression>
11 static const QRegularExpression
kQuotes{
"^\"|\"$"};
15 QByteArray ba = uri.toLatin1();
16 QUrl url = QUrl::fromEncoded(ba);
17 return url.toString();
20 QString
RelativeURI(
const QString& surl,
const QString& spath)
22 QUrl url = QUrl(surl);
23 QUrl path = QUrl(spath);
25 if (!path.isRelative())
28 return url.resolved(path).toString();
33 int p = line.indexOf(QLatin1String(
":"));
37 QStringList list = line.mid(
p + 1).split(
',');
38 for (
const auto & it : std::as_const(list))
40 QString arg = it.trimmed();
41 if (arg.startsWith(attr))
43 int pos = arg.indexOf(QLatin1String(
"="));
46 return arg.mid(pos+1);
58 int p = line.indexOf(QLatin1String(
":"));
62 for ( ; i < line.size(); i++)
63 if (!line[i].isNumber())
67 target = line.mid(
p + 1, i -
p - 1).toInt();
77 int p = line.indexOf(QLatin1String(
":"));
81 for ( ; i < line.size(); i++)
82 if (!line[i].isNumber())
86 target = line.mid(
p + 1, i -
p - 1).toInt();
106 LOG(VB_RECORD, LOG_ERR, loc +
107 "#EXT-X-VERSION: no protocol version found, should be version 1.");
112 if (version < 1 || version > 7)
114 LOG(VB_RECORD, LOG_ERR, loc +
115 QString(
"#EXT-X-VERSION is %1, but we only understand 1 to 7")
133 LOG(VB_RECORD, LOG_INFO, loc +
134 QString(
"Parsing stream from %1").arg(url));
148 LOG(VB_RECORD, LOG_INFO, loc +
149 "#EXT-X-STREAM-INF: No PROGRAM-ID=<value>, using 1");
160 LOG(VB_RECORD, LOG_ERR, loc +
161 "#EXT-X-STREAM-INF: expected BANDWIDTH=<value>");
164 bandwidth = attr.toInt();
168 LOG(VB_RECORD, LOG_ERR, loc +
169 "#EXT-X-STREAM-INF: bandwidth cannot be 0");
183 if (!audio.isEmpty())
186 LOG(VB_RECORD, LOG_INFO, loc +
187 QString(
"#EXT-X-STREAM-INF: attribute AUDIO=%1").arg(audio));
192 if (!video.isEmpty())
195 LOG(VB_RECORD, LOG_INFO, loc +
196 QString(
"#EXT-X-STREAM-INF: attribute VIDEO=%1").arg(video));
200 LOG(VB_RECORD, LOG_INFO, loc +
201 QString(
"bandwidth adaptation detected (program-id=%1, bandwidth=%2)")
202 .arg(
id).arg(bandwidth));
216 LOG(VB_RECORD, LOG_INFO, loc + QString(
"Parsing EXT-X-MEDIA line"));
242 LOG(VB_RECORD, LOG_ERR, loc +
"expected #EXT-X-TARGETDURATION:<s>");
250 int& duration, QString& title,
267 int p = line.indexOf(QLatin1String(
":"));
270 LOG(VB_RECORD, LOG_ERR, loc +
271 QString(
"ParseSegmentInformation: Missing ':' in '%1'")
276 QStringList list = line.mid(
p + 1).split(
',');
281 LOG(VB_RECORD, LOG_ERR, loc +
282 QString(
"ParseSegmentInformation: Missing arguments in '%1'")
289 const QString& val = list[0];
292 int duration_seconds = val.toInt(&ok);
295 duration = duration_seconds * 1000;
299 LOG(VB_RECORD, LOG_ERR, loc +
300 QString(
"ParseSegmentInformation: invalid duration in '%1'")
307 double d = val.toDouble(&ok);
310 LOG(VB_RECORD, LOG_ERR, loc +
311 QString(
"ParseSegmentInformation: invalid duration in '%1'")
315 duration =
static_cast<int>(
d * 1000);
318 if (list.size() >= 2)
328 const QString& line,
const QString& loc)
341 LOG(VB_RECORD, LOG_ERR, loc +
"expected #EXT-X-MEDIA-SEQUENCE:<s>");
349 [[maybe_unused]]
bool& aesmsg,
350 const QString& loc, QString &path, QString &iv)
365 LOG(VB_RECORD, LOG_ERR, loc +
"#EXT-X-KEY: expected METHOD=<value>");
369 if (attr.startsWith(QLatin1String(
"NONE")))
374 LOG(VB_RECORD, LOG_ERR, loc +
"#EXT-X-KEY: URI not expected");
381 if (!parsed_iv.isEmpty())
383 LOG(VB_RECORD, LOG_ERR, loc +
"#EXT-X-KEY: IV not expected");
388 #ifdef USING_LIBCRYPTO
389 else if (attr.startsWith(QLatin1String(
"AES-128")))
394 LOG(VB_RECORD, LOG_INFO, loc +
395 "playback of AES-128 encrypted HTTP Live media detected.");
401 LOG(VB_RECORD, LOG_ERR, loc +
"#EXT-X-KEY: URI not found for "
402 "encrypted HTTP Live media in AES-128");
407 path =
DecodedURI(uri.remove(QChar(QLatin1Char(
'"'))));
410 LOG(VB_RECORD, LOG_DEBUG, QString(
"M3U::ParseKey #EXT-X-KEY: %1").arg(line));
411 LOG(VB_RECORD, LOG_DEBUG, QString(
"M3U::ParseKey path:%1 IV:%2").arg(path, iv));
413 else if (attr.startsWith(QLatin1String(
"SAMPLE-AES")))
415 LOG(VB_RECORD, LOG_ERR, loc +
"encryption SAMPLE-AES not supported.");
422 LOG(VB_RECORD, LOG_ERR, loc +
423 "invalid encryption type, only NONE "
424 #ifdef USING_LIBCRYPTO
425 "and AES-128 are supported"
462 LOG(VB_RECORD, LOG_ERR, loc +
463 QString(
"Attribute URI not present in: #EXT-X-MAP %1")
476 int p = line.indexOf(QLatin1String(
":"));
479 LOG(VB_RECORD, LOG_ERR, loc +
480 QString(
"ParseProgramDateTime: Missing ':' in '%1'")
485 QString dt_string = line.mid(
p+1);
504 int pos = line.indexOf(QLatin1String(
":"));
507 LOG(VB_RECORD, LOG_ERR, loc +
508 QString(
"ParseAllowCache: missing ':' in '%1'")
512 QString answer = line.mid(pos+1, 3);
513 if (answer.size() < 2)
515 LOG(VB_RECORD, LOG_ERR, loc +
"#EXT-X-ALLOW-CACHE, ignoring ...");
518 do_cache = (!answer.startsWith(QLatin1String(
"NO")));
538 LOG(VB_RECORD, LOG_ERR, loc +
"expected #EXT-X-DISCONTINUITY-SEQUENCE:<s>");
542 LOG(VB_RECORD, LOG_DEBUG, loc + QString(
"#EXT-X-DISCONTINUITY-SEQUENCE %1")
550 LOG(VB_RECORD, LOG_DEBUG, loc + QString(
"#EXT-X-DISCONTINUITY %1")
563 LOG(VB_RECORD, LOG_INFO, loc +
" video on demand (vod) mode");
581 LOG(VB_RECORD, LOG_DEBUG, loc + QString(
"#EXT-X-INDEPENDENT-SEGMENTS %1")