From 55589e4aa9c27b02a83e0d01180fe1f901d715b0 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Thu, 1 Sep 2022 12:49:17 +0200 Subject: [PATCH] HLS input fixes + conversion to fully use the URIReader --- src/input/input.cpp | 2 +- src/input/input_hls.cpp | 63 ++++++++++++++++++++++++----------------- src/input/input_hls.h | 2 -- src/io.h | 1 + 4 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src/input/input.cpp b/src/input/input.cpp index f8732be2..6dd19b46 100644 --- a/src/input/input.cpp +++ b/src/input/input.cpp @@ -1424,7 +1424,7 @@ namespace Mist{ size_t dataLen; thisPacket.getString("data", data, dataLen); if (dataLen != parts.getSize(partNo)){ - INFO_MSG("Part size mismatch: %zu != %zu", dataLen, parts.getSize(partNo)); + INFO_MSG("Part %zu (@%" PRIu64 ") size mismatch: %zu (actual) != %zu (expected)", partNo, thisTime, dataLen, parts.getSize(partNo)); } ++partNo; HIGH_MSG("Buffering VoD packet (%zuB) @%" PRIu64 " ms on track %zu with offset %" PRIu64, dataLen, thisTime, idx, thisPacket.getInt("offset")); diff --git a/src/input/input_hls.cpp b/src/input/input_hls.cpp index dc999eb4..1529d653 100644 --- a/src/input/input_hls.cpp +++ b/src/input/input_hls.cpp @@ -134,6 +134,7 @@ namespace Mist{ /// Expects character array with playlist URL as argument, sets the first byte of the pointer to zero when loaded. void playlistRunner(void *ptr){ if (!ptr){return;}// abort if we received a null pointer - something is seriously wrong + Util::setStreamName(self->getStreamName()); bool initOnly = false; if (((char *)ptr)[0] == ';'){initOnly = true;} @@ -169,9 +170,8 @@ namespace Mist{ Playlist::Playlist(const std::string &uriSrc){ nextUTC = 0; id = 0; // to be set later - INFO_MSG("Adding variant playlist: %s", uriSrc.c_str()); - plsDL.dataTimeout = 15; - plsDL.retryCount = 8; + //If this is the copy constructor, just be silent. + if (uriSrc.size()){INFO_MSG("Adding variant playlist: %s", uriSrc.c_str());} lastFileIndex = 0; waitTime = 2; playlistEnd = false; @@ -180,8 +180,7 @@ namespace Mist{ root = HTTP::URL(uriSrc); if (root.isLocalPath()){ uri = root.getFilePath(); - } - else{ + }else{ uri = root.getUrl(); } memset(keyAES, 0, 16); @@ -370,13 +369,17 @@ namespace Mist{ std::ifstream fileSource; if (isUrl()){ - if (!plsDL.get(uri) || !plsDL.isOk()){ - FAIL_MSG("Could not download playlist '%s', aborting: %" PRIu32 " %s", uri.c_str(), - plsDL.getStatusCode(), plsDL.getStatusText().c_str()); + HTTP::URIReader plsDL; + plsDL.open(uri); + char * dataPtr; + size_t dataLen; + plsDL.readAll(dataPtr, dataLen); + if (!dataLen){ + FAIL_MSG("Could not download playlist '%s', aborting.", uri.c_str()); reloadNext = Util::bootSecs() + waitTime; return false; } - urlSource.str(plsDL.data()); + urlSource.str(std::string(dataPtr, dataLen)); }else{ fileSource.open(uri.c_str()); if (!fileSource.good()){ @@ -487,9 +490,7 @@ namespace Mist{ } // VOD over HTTP needs to be processed as LIVE. - if (isUrl()){ - playlistType = LIVE; - }else{ + if (!isUrl()){ fileSource.close(); } // Set the global live/vod bool to live if this playlist looks like a live playlist @@ -587,6 +588,12 @@ namespace Mist{ capa["source_match"].append("https://*.m3u"); capa["source_match"].append("https-hls://*"); capa["source_match"].append("http-hls://*"); + capa["source_match"].append("s3+http://*.m3u8"); + capa["source_match"].append("s3+http://*.m3u"); + capa["source_match"].append("s3+https://*.m3u8"); + capa["source_match"].append("s3+https://*.m3u"); + capa["source_match"].append("s3+https-hls://*"); + capa["source_match"].append("s3+http-hls://*"); // All URLs can be set to always-on mode. capa["always_match"] = capa["source_match"]; @@ -751,7 +758,7 @@ namespace Mist{ } tsStream.clear(); // set bootMsOffset in order to display the program time correctly in the player - meta.setUTCOffset(streamOffset + (Util::unixMS() - Util::bootMS())); + if (meta.getLive()){meta.setUTCOffset(streamOffset + (Util::unixMS() - Util::bootMS()));} meta.setBootMsOffset(streamOffset); return true; } @@ -842,7 +849,7 @@ namespace Mist{ } // set bootMsOffset in order to display the program time correctly in the player - meta.setUTCOffset(streamOffset + (Util::unixMS() - Util::bootMS())); + if (meta.getLive()){meta.setUTCOffset(streamOffset + (Util::unixMS() - Util::bootMS()));} meta.setBootMsOffset(streamOffset); if (streamIsLive || isLiveDVR){return true;} @@ -1001,7 +1008,7 @@ namespace Mist{ tsStream.getEarliestPacket(thisPacket); tid = getOriginalTrackId(currentPlaylist, thisPacket.getTrackId()); if (!tid){ - INFO_MSG("Track %zu on PLS %" PRIu64 " -> %" PRIu32, thisPacket.getTrackId(), currentPlaylist, tid); + INSANE_MSG("Track %zu on PLS %" PRIu64 " -> %" PRIu32, thisPacket.getTrackId(), currentPlaylist, tid); continue; } }else{ @@ -1014,7 +1021,7 @@ namespace Mist{ } uint64_t packetTime = getPacketTime(thisPacket.getTime(), tid, currentPlaylist, nUTC); - HIGH_MSG("Packet %" PRIu32 "@%" PRIu64 "ms -> %" PRIu64 "ms", tid, thisPacket.getTime(), packetTime); + INSANE_MSG("Packet %" PRIu32 "@%" PRIu64 "ms -> %" PRIu64 "ms", tid, thisPacket.getTime(), packetTime); // overwrite trackId on success Bit::htobl(thisPacket.getData() + 8, tid); Bit::htobll(thisPacket.getData() + 12, packetTime); @@ -1283,6 +1290,8 @@ namespace Mist{ // Convert custom http(s)-hls protocols into regular notation. if (playlistRootPath.protocol == "http-hls"){playlistRootPath.protocol = "http";} if (playlistRootPath.protocol == "https-hls"){playlistRootPath.protocol = "https";} + if (playlistRootPath.protocol == "s3+http-hls"){playlistRootPath.protocol = "s3+http";} + if (playlistRootPath.protocol == "s3+https-hls"){playlistRootPath.protocol = "s3+https";} std::istringstream urlSource; std::ifstream fileSource; @@ -1290,14 +1299,19 @@ namespace Mist{ bool isUrl = (playlistLocation.find("://") != std::string::npos); if (isUrl){ INFO_MSG("Downloading main playlist file from '%s'", uri.c_str()); - HTTP::Downloader plsDL; - plsDL.dataTimeout = 15; - plsDL.retryCount = 8; - if (!plsDL.get(playlistRootPath) || !plsDL.isOk()){ + HTTP::URIReader plsDL; + if (!plsDL.open(playlistRootPath) || !plsDL){ + FAIL_MSG("Could not open main playlist, aborting"); + return false; + } + char * dataPtr; + size_t dataLen; + plsDL.readAll(dataPtr, dataLen); + if (!dataLen){ FAIL_MSG("Could not download main playlist, aborting."); return false; } - urlSource.str(plsDL.data()); + urlSource.str(std::string(dataPtr, dataLen)); }else{ // If we're not a URL and there is no / at the start, ensure we get the full absolute path. if (playlistLocation[0] != '/'){ @@ -1464,7 +1478,8 @@ namespace Mist{ std::deque &curList = listEntries[currentPlaylist]; INSANE_MSG("Current playlist contains %li entries. Current index is %li in playlist %li", curList.size(), currentIndex, currentPlaylist); if (!curList.size()){ - WARN_MSG("no entries found in playlist: %" PRIu64 "!", currentPlaylist); + INFO_MSG("Reached last entry in playlist %" PRIu64 "; waiting for more segments", currentPlaylist); + if (streamIsLive || isLiveDVR){Util::wait(500);} return false; } if (!streamIsLive || isLiveDVR){ @@ -1479,10 +1494,6 @@ namespace Mist{ }else{ // Live does not use the currentIndex, but simply takes the first segment // That segment is then removed from the playlist so we don't read it again - live streams can't seek anyway - if (!curList.size()){ - INFO_MSG("Reached last entry"); - return false; - } ntry = *curList.begin(); curList.pop_front(); diff --git a/src/input/input_hls.h b/src/input/input_hls.h index 265247bd..5dc89080 100644 --- a/src/input/input_hls.h +++ b/src/input/input_hls.h @@ -68,8 +68,6 @@ namespace Mist{ std::string uri; // link to the current playlistfile HTTP::URL root; - HTTP::Downloader plsDL; - uint64_t reloadNext; uint32_t id; diff --git a/src/io.h b/src/io.h index e6545929..964ef5a0 100644 --- a/src/io.h +++ b/src/io.h @@ -34,6 +34,7 @@ namespace Mist{ size_t packDataSize, uint64_t packBytePos, bool isKeyframe); void bufferLivePacket(uint64_t packTime, int64_t packOffset, uint32_t packTrack, const char *packData, size_t packDataSize, uint64_t packBytePos, bool isKeyframe, DTSC::Meta & aMeta); + const std::string & getStreamName() const{return streamName;} protected: void updateTrackFromKeyframe(uint32_t packTrack, const char *packData, size_t packDataSize, DTSC::Meta & aMeta);