Fix playlist support not resuming on the correct page number and/or with the correct timestamp

This commit is contained in:
Thulinma 2021-02-19 22:40:01 +01:00
parent c9cd529927
commit 5f8518fe23
3 changed files with 59 additions and 32 deletions

View file

@ -623,6 +623,7 @@ namespace Mist {
return; return;
} }
nProxy.pagesByTrack.clear();
timeOffset = 0; timeOffset = 0;
uint64_t minFirstMs = 0; uint64_t minFirstMs = 0;
@ -631,6 +632,49 @@ namespace Mist {
if (config->getBool("realtime")){ if (config->getBool("realtime")){
seek(0); seek(0);
minFirstMs = 0xFFFFFFFFFFFFFFFFull;
uint64_t maxFirstMs = 0;
uint64_t minLastMs = 0xFFFFFFFFFFFFFFFFull;
uint64_t maxLastMs = 0;
//track lowest firstms value
for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); ++it){
if (it->second.firstms < minFirstMs){minFirstMs = it->second.firstms;}
if (it->second.firstms > maxFirstMs){maxFirstMs = it->second.firstms;}
if (it->second.lastms < minLastMs){minLastMs = it->second.lastms;}
if (it->second.lastms > maxLastMs){maxLastMs = it->second.lastms;}
}
if (maxFirstMs - minFirstMs > 500){
WARN_MSG("Begin timings of tracks for this file are %" PRIu64 " ms apart. This may mess up playback to some degree. (Range: %" PRIu64 "ms - %" PRIu64 "ms)", maxFirstMs-minFirstMs, minFirstMs, maxFirstMs);
}
if (maxLastMs - minLastMs > 500){
WARN_MSG("Stop timings of tracks for this file are %" PRIu64 " ms apart. This may mess up playback to some degree. (Range: %" PRIu64 "ms - %" PRIu64 "ms)", maxLastMs-minLastMs, minLastMs, maxLastMs);
}
bool needsWait = true;
//change firstms of all tracks to -1 to indicate we're resuming
std::map<unsigned int, uint64_t> preFirstMs;
for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); ++it){
preFirstMs[it->first] = it->second.firstms;
it->second.firstms = -1;
}
//negotiate all tracks with buffer
while (needsWait && config->is_active && nProxy.userClient.isAlive()){
needsWait = false;
for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); ++it){
if (!it->first){continue;}
if (nProxy.trackState.count(it->first) && nProxy.trackState[it->first] == FILL_ACC){continue;}
nProxy.continueNegotiate(it->first, myMeta);
if (nProxy.trackState.count(it->first) && nProxy.trackState[it->first] == FILL_ACC){continue;}
needsWait = true;
}
if (needsWait){Util::sleep(200);}
}
//Restore firstms of tracks - should not be needed, but why risk messing things up..?
for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); ++it){
it->second.firstms = preFirstMs[it->first];
}
char nameBuf[NAME_BUFFER_SIZE]; char nameBuf[NAME_BUFFER_SIZE];
snprintf(nameBuf, NAME_BUFFER_SIZE, SHM_STREAM_INDEX, streamName.c_str()); snprintf(nameBuf, NAME_BUFFER_SIZE, SHM_STREAM_INDEX, streamName.c_str());
@ -653,33 +697,16 @@ namespace Mist {
liveSem = 0; liveSem = 0;
} }
DTSC::Meta tmpM(tmpMeta); DTSC::Meta tmpM(tmpMeta);
minFirstMs = 0xFFFFFFFFFFFFFFFFull;
uint64_t maxFirstMs = 0;
uint64_t minLastMs = 0xFFFFFFFFFFFFFFFFull;
uint64_t maxLastMs = 0;
//track lowest firstms value
for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); ++it){
if (it->second.firstms < minFirstMs){minFirstMs = it->second.firstms;}
if (it->second.firstms > maxFirstMs){maxFirstMs = it->second.firstms;}
if (it->second.lastms < minLastMs){minLastMs = it->second.lastms;}
if (it->second.lastms > maxLastMs){maxLastMs = it->second.lastms;}
}
if (maxFirstMs - minFirstMs > 500){
WARN_MSG("Begin timings of tracks for this file are %" PRIu64 " ms apart. This may mess up playback to some degree. (Range: %" PRIu64 "ms - %" PRIu64 "ms)", maxFirstMs-minFirstMs, minFirstMs, maxFirstMs);
}
if (maxLastMs - minLastMs > 500){
WARN_MSG("Stop timings of tracks for this file are %" PRIu64 " ms apart. This may mess up playback to some degree. (Range: %" PRIu64 "ms - %" PRIu64 "ms)", maxLastMs-minLastMs, minLastMs, maxLastMs);
}
//find highest current time //find highest current time
for (std::map<unsigned int, DTSC::Track>::iterator secondIt = tmpM.tracks.begin(); secondIt != tmpM.tracks.end(); ++secondIt){ for (std::map<unsigned int, DTSC::Track>::iterator secondIt = tmpM.tracks.begin(); secondIt != tmpM.tracks.end(); ++secondIt){
VERYHIGH_MSG("Track %u starts at %" PRIu64, secondIt->first, secondIt->second.lastms);
timeOffset = std::max(timeOffset, (int64_t)secondIt->second.lastms); timeOffset = std::max(timeOffset, (int64_t)secondIt->second.lastms);
} }
if (timeOffset){ if (timeOffset){
if (minFirstMs == 0xFFFFFFFFFFFFFFFFull){minFirstMs = 0;} if (minFirstMs == 0xFFFFFFFFFFFFFFFFull){minFirstMs = 0;}
MEDIUM_MSG("Offset is %" PRId64 ", adding 1s and subtracting the start time of %" PRIu64, timeOffset, minFirstMs); MEDIUM_MSG("Offset is %" PRId64 "ms, adding 40ms and subtracting the start time of %" PRIu64, timeOffset, minFirstMs);
timeOffset += 1000;//Add an artificial frame at 25 FPS to make sure we append, not overwrite timeOffset += 40;//Add an artificial frame at 25 FPS to make sure we append, not overwrite
timeOffset -= minFirstMs;//we don't need to add the lowest firstms value to the offset, as it's already there timeOffset -= minFirstMs;//we don't need to add the lowest firstms value to the offset, as it's already there
} }
} }
@ -690,7 +717,6 @@ namespace Mist {
selectedTracks.insert(it->first); selectedTracks.insert(it->first);
it->second.minKeepAway = SIMULATED_LIVE_BUFFER; it->second.minKeepAway = SIMULATED_LIVE_BUFFER;
} }
nProxy.pagesByTrack.clear();
simStartTime = config->getInteger("simulated-starttime"); simStartTime = config->getInteger("simulated-starttime");
if (!simStartTime){simStartTime = Util::bootMS();} if (!simStartTime){simStartTime = Util::bootMS();}

View file

@ -656,6 +656,7 @@ namespace Mist {
negotiatingTracks.erase(value); negotiatingTracks.erase(value);
} }
if (activeTracks.count(value)) { if (activeTracks.count(value)) {
updateTrackMeta(value);
updateMeta(); updateMeta();
activeTracks.erase(value); activeTracks.erase(value);
if (!config->getBool("resume")){ if (!config->getBool("resume")){
@ -809,7 +810,7 @@ namespace Mist {
int collidesWith = -1; int collidesWith = -1;
std::string newTrackIdentifier = trackMeta.tracks.find(value)->second.getIdentifier(); std::string newTrackIdentifier = trackMeta.tracks.find(value)->second.getIdentifier();
std::string newTrackInit = trackMeta.tracks.find(value)->second.init; std::string newTrackInit = trackMeta.tracks.find(value)->second.init;
INFO_MSG("Attempting colision detection for track %s", newTrackIdentifier.c_str()); MEDIUM_MSG("Attempting collision detection for track %s", newTrackIdentifier.c_str());
//First check for matches on INIT data //First check for matches on INIT data
for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++) { for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++) {
@ -845,7 +846,7 @@ namespace Mist {
if (finalMap == -1) { if (finalMap == -1) {
//No collision has been detected, assign a new final number //No collision has been detected, assign a new final number
finalMap = (myMeta.tracks.size() ? myMeta.tracks.rbegin()->first : 0) + 1; finalMap = (myMeta.tracks.size() ? myMeta.tracks.rbegin()->first : 0) + 1;
MEDIUM_MSG("No colision detected for temporary track %lu from user %u, assigning final track number %lu", value, id, finalMap); MEDIUM_MSG("No collision detected for temporary track %lu from user %u, assigning final track number %lu", value, id, finalMap);
/*LTS-START*/ /*LTS-START*/
if (Triggers::shouldTrigger("STREAM_TRACK_ADD")) { if (Triggers::shouldTrigger("STREAM_TRACK_ADD")) {
std::string payload = config->getString("streamname") + "\n" + JSON::Value(finalMap).asString() + "\n"; std::string payload = config->getString("streamname") + "\n" + JSON::Value(finalMap).asString() + "\n";
@ -884,7 +885,7 @@ namespace Mist {
pushLocation[finalMap] = data; pushLocation[finalMap] = data;
//Initialize the metadata for this track if it was not in place yet. //Initialize the metadata for this track if it was not in place yet.
if (!myMeta.tracks.count(finalMap)) { if (!myMeta.tracks.count(finalMap)) {
DEBUG_MSG(DLVL_MEDIUM, "Inserting metadata for track number %d", finalMap); DEBUG_MSG(DLVL_MEDIUM, "Inserting metadata for track number %" PRIu64, finalMap);
myMeta.tracks[finalMap] = trackMeta.tracks.begin()->second; myMeta.tracks[finalMap] = trackMeta.tracks.begin()->second;
myMeta.tracks[finalMap].firstms = 0; myMeta.tracks[finalMap].firstms = 0;
myMeta.tracks[finalMap].lastms = 0; myMeta.tracks[finalMap].lastms = 0;
@ -936,7 +937,7 @@ namespace Mist {
//Add an entry into bufferLocations[tNum] for the pages we haven't handled yet. //Add an entry into bufferLocations[tNum] for the pages we haven't handled yet.
if (!locations.count(keyNum)) { if (!locations.count(keyNum)) {
locations[keyNum].curOffset = 0; locations[keyNum].curOffset = 0;
VERYHIGH_MSG("Page %d detected, with %d keys", keyNum, Bit::btohl(tmpOffset+4)); VERYHIGH_MSG("Page %lu detected, with %" PRIu32 " keys", keyNum, Bit::btohl(tmpOffset+4));
} }
locations[keyNum].pageNum = keyNum; locations[keyNum].pageNum = keyNum;
locations[keyNum].keyNum = Bit::btohl(tmpOffset+4); locations[keyNum].keyNum = Bit::btohl(tmpOffset+4);
@ -948,7 +949,7 @@ namespace Mist {
} }
void inputBuffer::updateMetaFromPage(unsigned long tNum, unsigned long pageNum) { void inputBuffer::updateMetaFromPage(unsigned long tNum, unsigned long pageNum) {
VERYHIGH_MSG("Updating meta for track %d page %d", tNum, pageNum); VERYHIGH_MSG("Updating meta for track %lu page %lu", tNum, pageNum);
DTSCPageData & pageData = bufferLocations[tNum][pageNum]; DTSCPageData & pageData = bufferLocations[tNum][pageNum];
//If the current page is over its 8mb "splitting" boundary //If the current page is over its 8mb "splitting" boundary

View file

@ -487,7 +487,7 @@ namespace Mist {
continueNegotiate(tid, myMeta); continueNegotiate(tid, myMeta);
//If the track is declined, stop here //If the track is declined, stop here
if (trackState[tid] == FILL_DEC) { if (trackState[tid] == FILL_DEC) {
INFO_MSG("Track %lu declined", tid); WARN_MSG("Track %lu declined", tid);
preBuffer[tid].clear(); preBuffer[tid].clear();
return; return;
} }
@ -496,7 +496,6 @@ namespace Mist {
preBuffer[tid].push_back(packet); preBuffer[tid].push_back(packet);
}else{ }else{
if (preBuffer[tid].size()){ if (preBuffer[tid].size()){
INFO_MSG("Track %lu accepted as track %lu", tid, trackMap[tid] );
while (preBuffer[tid].size()){ while (preBuffer[tid].size()){
bufferSinglePacket(preBuffer[tid].front(), myMeta); bufferSinglePacket(preBuffer[tid].front(), myMeta);
preBuffer[tid].pop_front(); preBuffer[tid].pop_front();
@ -543,13 +542,14 @@ namespace Mist {
//If there is no page, create it //If there is no page, create it
if (!pagesByTrack.count(tid) || pagesByTrack[tid].size() == 0) { if (!pagesByTrack.count(tid) || pagesByTrack[tid].size() == 0) {
nextPageNum = 1; nextPageNum = 1;
pagesByTrack[tid][1].dataSize = DEFAULT_DATA_PAGE_SIZE;//Initialize op 25mb pagesByTrack[tid][nextPageNum].dataSize = DEFAULT_DATA_PAGE_SIZE;//Initialize op 25mb
pagesByTrack[tid][1].pageNum = 1; pagesByTrack[tid][nextPageNum].pageNum = nextPageNum;
pagesByTrack[tid][1].firstTime = packet.getTime(); pagesByTrack[tid][nextPageNum].curOffset = 0;
pagesByTrack[tid][nextPageNum].firstTime = packet.getTime();
} }
//Take the last allocated page //Take the last allocated page
std::map<unsigned long, DTSCPageData>::reverse_iterator tmpIt = pagesByTrack[tid].rbegin(); std::map<unsigned long, DTSCPageData>::reverse_iterator tmpIt = pagesByTrack[tid].rbegin();
int currentPageNum = tmpIt->second.pageNum; unsigned long currentPageNum = tmpIt->first;
if (!pagesByTrack[tid][currentPageNum].curOffset) { if (!pagesByTrack[tid][currentPageNum].curOffset) {
pagesByTrack[tid][currentPageNum].firstTime = packet.getTime(); pagesByTrack[tid][currentPageNum].firstTime = packet.getTime();
} }