#include "../include/M3U8.hpp" #include namespace QuickMedia { // static M3U8Stream M3U8Stream::get_highest_resolution_stream(const std::vector &streams) { auto streams_copy = streams; std::sort(streams_copy.begin(), streams_copy.end(), [](const M3U8Stream &stream1, const M3U8Stream &stream2) { return stream1.height > stream2.height; }); return streams_copy.front(); } // TODO: Extract framerate static bool stream_metadata_from_string(const std::string &metadata_str, M3U8Stream &stream) { size_t index = metadata_str.find("RESOLUTION="); if(index == std::string::npos) return false; index += 11; int width = 0; int height = 0; if(sscanf(metadata_str.c_str() + index, "%dx%d", &width, &height) != 2) return false; stream.width = width; stream.height = height; return true; } static bool stream_extract_url(const std::string &m3u8_data, size_t offset, std::string &url) { if(offset >= m3u8_data.size()) return false; if(m3u8_data[offset] == '#') return false; size_t line_end = m3u8_data.find("\n", offset); if(line_end == std::string::npos) line_end = m3u8_data.size(); url = m3u8_data.substr(offset, line_end - offset); return true; } // TODO: Also check for EXT-X-I-FRAME-STREAM-INF? std::vector m3u8_get_streams(const std::string &m3u8_data) { std::vector streams; size_t index = 0; while(index < m3u8_data.size()) { index = m3u8_data.find("#EXT-X-STREAM-INF:", index); if(index == std::string::npos) break; index += 18; size_t line_end = m3u8_data.find("\n", index); if(line_end == std::string::npos) line_end = m3u8_data.size(); std::string stream_metadata = m3u8_data.substr(index, line_end - index); M3U8Stream stream; if(stream_metadata_from_string(stream_metadata, stream) && stream_extract_url(m3u8_data, line_end + 1, stream.url)) { index = line_end + 1 + stream.url.size() + 1; streams.push_back(std::move(stream)); } else { index = line_end + 1; } } return streams; } }