/* * Copyright (c) 2020 The ZLMediaKit project authors. All Rights Reserved. * * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ #include #include #include "HlsParser.h" #include "Util/util.h" #include "Common/Parser.h" using namespace std; using namespace toolkit; namespace mediakit { bool HlsParser::parse(const string &http_url, const string &m3u8) { float extinf_dur = 0; ts_segment segment; map ts_map; _total_dur = 0; _is_live = true; _is_m3u8_inner = false; int index = 0; auto lines = split(m3u8, "\n"); for (auto &line : lines) { trim(line); if (line.size() < 2) { continue; } if ((_is_m3u8_inner || extinf_dur != 0) && line[0] != '#') { segment.duration = extinf_dur; segment.url = Parser::mergeUrl(http_url, line); if (!_is_m3u8_inner) { // ts按照先后顺序排序 [AUTO-TRANSLATED:c34f8c9d] // Sort by order of appearance ts_map.emplace(index++, segment); } else { // 子m3u8按照带宽排序 [AUTO-TRANSLATED:749cb42b] // Sort sub m3u8 by bandwidth ts_map.emplace(segment.bandwidth, segment); } extinf_dur = 0; continue; } _is_m3u8_inner = false; if (line.find("#EXTINF:") == 0) { sscanf(line.data(), "#EXTINF:%f,", &extinf_dur); _total_dur += extinf_dur; continue; } static const string s_stream_inf = "#EXT-X-STREAM-INF:"; if (line.find(s_stream_inf) == 0) { _is_m3u8_inner = true; auto key_val = Parser::parseArgs(line.substr(s_stream_inf.size()), ",", "="); segment.program_id = atoi(key_val["PROGRAM-ID"].data()); segment.bandwidth = atoi(key_val["BANDWIDTH"].data()); sscanf(key_val["RESOLUTION"].data(), "%dx%d", &segment.width, &segment.height); continue; } if (line == "#EXTM3U") { _is_m3u8 = true; continue; } if (line.find("#EXT-X-ALLOW-CACHE:") == 0) { _allow_cache = (line.find(":YES") != string::npos); continue; } if (line.find("#EXT-X-VERSION:") == 0) { sscanf(line.data(), "#EXT-X-VERSION:%d", &_version); continue; } if (line.find("#EXT-X-TARGETDURATION:") == 0) { sscanf(line.data(), "#EXT-X-TARGETDURATION:%d", &_target_dur); continue; } if (line.find("#EXT-X-MEDIA-SEQUENCE:") == 0) { sscanf(line.data(), "#EXT-X-MEDIA-SEQUENCE:%" PRId64, &_sequence); continue; } if (line.find("#EXT-X-ENDLIST") == 0) { // 点播 [AUTO-TRANSLATED:a64427bc] // On-demand _is_live = false; continue; } continue; } return _is_m3u8 && onParsed(_is_m3u8_inner, _sequence, ts_map); } bool HlsParser::isM3u8() const { return _is_m3u8; } bool HlsParser::isLive() const { return _is_live; } bool HlsParser::allowCache() const { return _allow_cache; } int HlsParser::getVersion() const { return _version; } int HlsParser::getTargetDur() const { return _target_dur; } int64_t HlsParser::getSequence() const { return _sequence; } bool HlsParser::isM3u8Inner() const { return _is_m3u8_inner; } float HlsParser::getTotalDuration() const { return _total_dur; } }//namespace mediakit