From 08e5ceca2b250d8de1c917e41ea3257937510142 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Fri, 24 Jan 2020 00:05:06 +0100 Subject: [PATCH] Improvements and backports for HLS input --- src/input/input_hls.cpp | 70 +++++++++++++++++++++++++++-------------- src/input/input_hls.h | 3 +- 2 files changed, 48 insertions(+), 25 deletions(-) diff --git a/src/input/input_hls.cpp b/src/input/input_hls.cpp index 5b39dad7..ea49c678 100644 --- a/src/input/input_hls.cpp +++ b/src/input/input_hls.cpp @@ -71,12 +71,24 @@ static uint64_t ISO8601toUnixmillis(const std::string &ts){ { unsigned long hrs, mins; if (sscanf(zone.c_str() + 1, "%lu:%lu", &hrs, &mins) == 2){ - unxTime += mins * 60000 + hrs * 3600000; + if (sign){ + unxTime += mins * 60000 + hrs * 3600000; + }else{ + unxTime -= mins * 60000 + hrs * 3600000; + } }else if (sscanf(zone.c_str() + 1, "%lu", &hrs) == 1){ if (hrs > 100){ - unxTime += (hrs % 100) * 60000 + ((uint64_t)(hrs / 100)) * 3600000; + if (sign){ + unxTime += (hrs % 100) * 60000 + ((uint64_t)(hrs / 100)) * 3600000; + }else{ + unxTime -= (hrs % 100) * 60000 + ((uint64_t)(hrs / 100)) * 3600000; + } }else{ - unxTime += hrs * 3600000; + if (sign){ + unxTime += hrs * 3600000; + }else{ + unxTime -= hrs * 3600000; + } } }else{ WARN_MSG("Could not parse time zone '%s'; assuming UTC", zone.c_str()); @@ -267,13 +279,13 @@ namespace Mist{ // check first byte = 0x47. begin of ts file, then check if it is a multiple of 188bytes if (segDL.data().data()[0] == 0x47){ if (segDL.data().size() % 188){ - FAIL_MSG("Expected a multiple of 188 bytes, received %d bytes. url: %s", + FAIL_MSG("Expected a multiple of 188 bytes, received %zu bytes. url: %s", segDL.data().size(), entry.filename.c_str()); return false; } }else if (segDL.data().data()[5] == 0x47){ if (segDL.data().size() % 192){ - FAIL_MSG("Expected a multiple of 192 bytes, received %d bytes. url: %s", + FAIL_MSG("Expected a multiple of 192 bytes, received %zu bytes. url: %s", segDL.data().size(), entry.filename.c_str()); return false; } @@ -310,7 +322,9 @@ namespace Mist{ if (isUrl()){ if (!plsDL.get(uri) || !plsDL.isOk()){ - FAIL_MSG("Could not download playlist, aborting."); + FAIL_MSG("Could not download playlist '%s', aborting: %" PRIu32 " %s", uri.c_str(), + plsDL.getStatusCode(), plsDL.getStatusText().c_str()); + reloadNext = Util::bootSecs() + waitTime; return false; } urlSource.str(plsDL.data()); @@ -318,6 +332,8 @@ namespace Mist{ fileSource.open(uri.c_str()); if (!fileSource.good()){ FAIL_MSG("Could not open playlist (%s): %s", strerror(errno), uri.c_str()); + reloadNext = Util::bootSecs() + waitTime; + return false; } } @@ -475,8 +491,8 @@ namespace Mist{ // The mutex assures we have a unique count/number. if (!id){id = listEntries.size() + 1;} listEntries[id].push_back(entry); - MEDIUM_MSG("Added segment to variant %" PRIu32 " (#%d, now %d queued): %s", id, lastFileIndex, - listEntries[id].size(), filename.c_str()); + MEDIUM_MSG("Added segment to variant %" PRIu32 " (#%d, now %zu queued): %s", id, + lastFileIndex, listEntries[id].size(), filename.c_str()); } } @@ -553,10 +569,6 @@ namespace Mist{ TS::Packet packet; // to analyse and extract data int counter = 1; - char *data; - unsigned int dataLen; - bool keepReading = false; - tthread::lock_guard guard(entryMutex); for (std::map >::iterator pListIt = listEntries.begin(); pListIt != listEntries.end(); pListIt++){ @@ -639,10 +651,9 @@ namespace Mist{ TS::Packet packet; // to analyse and extract data - int counter = 1; - char *data; size_t dataLen; + int counter = 1; tthread::lock_guard guard(entryMutex); for (std::map >::iterator pListIt = listEntries.begin(); @@ -807,9 +818,11 @@ namespace Mist{ if (plsTimeOffset.count(currentPlaylist)){newTime += plsTimeOffset[currentPlaylist];} if (zUTC){ - //UTC based timestamp offsets - if (allowRemap && nUTC){ + if (allowSoftRemap && thisPacket.getTime() < 1000){allowSoftRemap = false;} + // UTC based timestamp offsets + if ((allowRemap || allowSoftRemap) && nUTC){ allowRemap = false; + allowSoftRemap = !thisPacket.getTime(); int64_t prevOffset = plsTimeOffset[currentPlaylist]; plsTimeOffset[currentPlaylist] = (nUTC - zUTC) - thisPacket.getTime(); newTime = thisPacket.getTime() + plsTimeOffset[currentPlaylist]; @@ -818,14 +831,16 @@ namespace Mist{ prevOffset, plsTimeOffset[currentPlaylist], tid, thisPacket.getTime(), newTime); } }else{ - //Non-UTC based + // Non-UTC based if (plsLastTime.count(currentPlaylist)){ if (plsInterval.count(currentPlaylist)){ - if (allowRemap && (newTime < plsLastTime[currentPlaylist] || newTime > plsLastTime[currentPlaylist] + plsInterval[currentPlaylist] * 60)){ + if (allowRemap && (newTime < plsLastTime[currentPlaylist] || + newTime > plsLastTime[currentPlaylist] + plsInterval[currentPlaylist] * 60)){ allowRemap = false; // time difference too great, change offset to correct for it int64_t prevOffset = plsTimeOffset[currentPlaylist]; - plsTimeOffset[currentPlaylist] += (int64_t)(plsLastTime[currentPlaylist] + plsInterval[currentPlaylist]) - (int64_t)newTime; + plsTimeOffset[currentPlaylist] += + (int64_t)(plsLastTime[currentPlaylist] + plsInterval[currentPlaylist]) - (int64_t)newTime; newTime = thisPacket.getTime() + plsTimeOffset[currentPlaylist]; INFO_MSG("[Guess; New offset: %" PRId64 " -> %" PRId64 "] Packet %lu@%" PRIu64 "ms -> %" PRIu64 "ms", @@ -834,7 +849,8 @@ namespace Mist{ } // check if time increased, and no increase yet or is less than current, set new interval if (newTime > plsLastTime[currentPlaylist] && - (!plsInterval.count(currentPlaylist) || newTime - plsLastTime[currentPlaylist] < plsInterval[currentPlaylist])){ + (!plsInterval.count(currentPlaylist) || + newTime - plsLastTime[currentPlaylist] < plsInterval[currentPlaylist])){ plsInterval[currentPlaylist] = newTime - plsLastTime[currentPlaylist]; } } @@ -842,7 +858,7 @@ namespace Mist{ plsLastTime[tid] = newTime; } - DONTEVEN_MSG("Packet %lu@%" PRIu64 "ms -> %ms" PRIu64, tid, thisPacket.getTime(), newTime); + DONTEVEN_MSG("Packet %" PRIu32 "@%" PRIu64 "ms -> %" PRIu64 "ms", tid, thisPacket.getTime(), newTime); // overwrite trackId on success Bit::htobl(thisPacket.getData() + 8, tid); Bit::htobll(thisPacket.getData() + 12, newTime); @@ -877,11 +893,17 @@ namespace Mist{ } // Now that we know our playlist is up-to-date, actually try to read the file. - VERYHIGH_MSG("Moving on to next TS segment (variant %u)", currentPlaylist); + VERYHIGH_MSG("Moving on to next TS segment (variant %" PRIu32 ")", currentPlaylist); if (readNextFile()){ MEDIUM_MSG("Next segment read successfully"); endOfFile = false; // no longer at end of file continue; // Success! Continue regular parsing. + }else{ + // failed to read segment for playlist, dropping it + WARN_MSG("Dropping variant %" PRIu32 " because we couldn't read anything from it", currentPlaylist); + tthread::lock_guard guard(entryMutex); + listEntries.erase(currentPlaylist); + if (listEntries.size()){continue;} } // Nothing works! @@ -894,7 +916,6 @@ namespace Mist{ void inputHLS::readPMT(){ HIGH_MSG("readPMT()"); - size_t bpos; TS::Packet tsBuffer; const char *tmpPtr = segDowner.segDL.data().data(); @@ -1159,9 +1180,10 @@ namespace Mist{ return readNextFile(); // Attempt to read another, if possible. } nUTC = ntry.mUTC; - //If we don't have a zero-time yet, guess an hour before this UTC time is probably fine + // If we don't have a zero-time yet, guess an hour before this UTC time is probably fine if (nUTC && !zUTC){zUTC = nUTC - 3600000;} allowRemap = true; + allowSoftRemap = false; return true; } diff --git a/src/input/input_hls.h b/src/input/input_hls.h index 4c9773c0..5822df17 100644 --- a/src/input/input_hls.h +++ b/src/input/input_hls.h @@ -96,7 +96,8 @@ namespace Mist{ bool endPlaylist; int currentPlaylist; - bool allowRemap; ///< True if the next packet may remap the timestamps + bool allowRemap; ///< True if the next packet may remap the timestamps + bool allowSoftRemap; ///< True if the next packet may soft-remap the timestamps std::map pidMapping; std::map pidMappingR; std::map plsTimeOffset;