Improvements and backports for HLS input

This commit is contained in:
Thulinma 2020-01-24 00:05:06 +01:00
parent 3e607d864e
commit 08e5ceca2b
2 changed files with 48 additions and 25 deletions

View file

@ -71,12 +71,24 @@ static uint64_t ISO8601toUnixmillis(const std::string &ts){
{ {
unsigned long hrs, mins; unsigned long hrs, mins;
if (sscanf(zone.c_str() + 1, "%lu:%lu", &hrs, &mins) == 2){ 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){ }else if (sscanf(zone.c_str() + 1, "%lu", &hrs) == 1){
if (hrs > 100){ 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{ }else{
unxTime += hrs * 3600000; if (sign){
unxTime += hrs * 3600000;
}else{
unxTime -= hrs * 3600000;
}
} }
}else{ }else{
WARN_MSG("Could not parse time zone '%s'; assuming UTC", zone.c_str()); 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 // 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().data()[0] == 0x47){
if (segDL.data().size() % 188){ 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()); segDL.data().size(), entry.filename.c_str());
return false; return false;
} }
}else if (segDL.data().data()[5] == 0x47){ }else if (segDL.data().data()[5] == 0x47){
if (segDL.data().size() % 192){ 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()); segDL.data().size(), entry.filename.c_str());
return false; return false;
} }
@ -310,7 +322,9 @@ namespace Mist{
if (isUrl()){ if (isUrl()){
if (!plsDL.get(uri) || !plsDL.isOk()){ 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; return false;
} }
urlSource.str(plsDL.data()); urlSource.str(plsDL.data());
@ -318,6 +332,8 @@ namespace Mist{
fileSource.open(uri.c_str()); fileSource.open(uri.c_str());
if (!fileSource.good()){ if (!fileSource.good()){
FAIL_MSG("Could not open playlist (%s): %s", strerror(errno), uri.c_str()); 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. // The mutex assures we have a unique count/number.
if (!id){id = listEntries.size() + 1;} if (!id){id = listEntries.size() + 1;}
listEntries[id].push_back(entry); listEntries[id].push_back(entry);
MEDIUM_MSG("Added segment to variant %" PRIu32 " (#%d, now %d queued): %s", id, lastFileIndex, MEDIUM_MSG("Added segment to variant %" PRIu32 " (#%d, now %zu queued): %s", id,
listEntries[id].size(), filename.c_str()); lastFileIndex, listEntries[id].size(), filename.c_str());
} }
} }
@ -553,10 +569,6 @@ namespace Mist{
TS::Packet packet; // to analyse and extract data TS::Packet packet; // to analyse and extract data
int counter = 1; int counter = 1;
char *data;
unsigned int dataLen;
bool keepReading = false;
tthread::lock_guard<tthread::mutex> guard(entryMutex); tthread::lock_guard<tthread::mutex> guard(entryMutex);
for (std::map<uint32_t, std::deque<playListEntries> >::iterator pListIt = listEntries.begin(); for (std::map<uint32_t, std::deque<playListEntries> >::iterator pListIt = listEntries.begin();
pListIt != listEntries.end(); pListIt++){ pListIt != listEntries.end(); pListIt++){
@ -639,10 +651,9 @@ namespace Mist{
TS::Packet packet; // to analyse and extract data TS::Packet packet; // to analyse and extract data
int counter = 1;
char *data; char *data;
size_t dataLen; size_t dataLen;
int counter = 1;
tthread::lock_guard<tthread::mutex> guard(entryMutex); tthread::lock_guard<tthread::mutex> guard(entryMutex);
for (std::map<uint32_t, std::deque<playListEntries> >::iterator pListIt = listEntries.begin(); for (std::map<uint32_t, std::deque<playListEntries> >::iterator pListIt = listEntries.begin();
@ -807,9 +818,11 @@ namespace Mist{
if (plsTimeOffset.count(currentPlaylist)){newTime += plsTimeOffset[currentPlaylist];} if (plsTimeOffset.count(currentPlaylist)){newTime += plsTimeOffset[currentPlaylist];}
if (zUTC){ if (zUTC){
//UTC based timestamp offsets if (allowSoftRemap && thisPacket.getTime() < 1000){allowSoftRemap = false;}
if (allowRemap && nUTC){ // UTC based timestamp offsets
if ((allowRemap || allowSoftRemap) && nUTC){
allowRemap = false; allowRemap = false;
allowSoftRemap = !thisPacket.getTime();
int64_t prevOffset = plsTimeOffset[currentPlaylist]; int64_t prevOffset = plsTimeOffset[currentPlaylist];
plsTimeOffset[currentPlaylist] = (nUTC - zUTC) - thisPacket.getTime(); plsTimeOffset[currentPlaylist] = (nUTC - zUTC) - thisPacket.getTime();
newTime = thisPacket.getTime() + plsTimeOffset[currentPlaylist]; newTime = thisPacket.getTime() + plsTimeOffset[currentPlaylist];
@ -818,14 +831,16 @@ namespace Mist{
prevOffset, plsTimeOffset[currentPlaylist], tid, thisPacket.getTime(), newTime); prevOffset, plsTimeOffset[currentPlaylist], tid, thisPacket.getTime(), newTime);
} }
}else{ }else{
//Non-UTC based // Non-UTC based
if (plsLastTime.count(currentPlaylist)){ if (plsLastTime.count(currentPlaylist)){
if (plsInterval.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; allowRemap = false;
// time difference too great, change offset to correct for it // time difference too great, change offset to correct for it
int64_t prevOffset = plsTimeOffset[currentPlaylist]; 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]; newTime = thisPacket.getTime() + plsTimeOffset[currentPlaylist];
INFO_MSG("[Guess; New offset: %" PRId64 " -> %" PRId64 "] Packet %lu@%" PRIu64 INFO_MSG("[Guess; New offset: %" PRId64 " -> %" PRId64 "] Packet %lu@%" PRIu64
"ms -> %" PRIu64 "ms", "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 // check if time increased, and no increase yet or is less than current, set new interval
if (newTime > plsLastTime[currentPlaylist] && 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]; plsInterval[currentPlaylist] = newTime - plsLastTime[currentPlaylist];
} }
} }
@ -842,7 +858,7 @@ namespace Mist{
plsLastTime[tid] = newTime; 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 // overwrite trackId on success
Bit::htobl(thisPacket.getData() + 8, tid); Bit::htobl(thisPacket.getData() + 8, tid);
Bit::htobll(thisPacket.getData() + 12, newTime); 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. // 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()){ if (readNextFile()){
MEDIUM_MSG("Next segment read successfully"); MEDIUM_MSG("Next segment read successfully");
endOfFile = false; // no longer at end of file endOfFile = false; // no longer at end of file
continue; // Success! Continue regular parsing. 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<tthread::mutex> guard(entryMutex);
listEntries.erase(currentPlaylist);
if (listEntries.size()){continue;}
} }
// Nothing works! // Nothing works!
@ -894,7 +916,6 @@ namespace Mist{
void inputHLS::readPMT(){ void inputHLS::readPMT(){
HIGH_MSG("readPMT()"); HIGH_MSG("readPMT()");
size_t bpos;
TS::Packet tsBuffer; TS::Packet tsBuffer;
const char *tmpPtr = segDowner.segDL.data().data(); const char *tmpPtr = segDowner.segDL.data().data();
@ -1159,9 +1180,10 @@ namespace Mist{
return readNextFile(); // Attempt to read another, if possible. return readNextFile(); // Attempt to read another, if possible.
} }
nUTC = ntry.mUTC; 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;} if (nUTC && !zUTC){zUTC = nUTC - 3600000;}
allowRemap = true; allowRemap = true;
allowSoftRemap = false;
return true; return true;
} }

View file

@ -96,7 +96,8 @@ namespace Mist{
bool endPlaylist; bool endPlaylist;
int currentPlaylist; 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<uint64_t, uint64_t> pidMapping; std::map<uint64_t, uint64_t> pidMapping;
std::map<uint64_t, uint64_t> pidMappingR; std::map<uint64_t, uint64_t> pidMappingR;
std::map<int, int64_t> plsTimeOffset; std::map<int, int64_t> plsTimeOffset;