diff --git a/src/input/input_ebml.cpp b/src/input/input_ebml.cpp index 440763f2..0bbecb5f 100644 --- a/src/input/input_ebml.cpp +++ b/src/input/input_ebml.cpp @@ -407,7 +407,7 @@ namespace Mist{ bench = Util::getMicros(bench); INFO_MSG("Header generated in %llu ms", bench / 1000); - packBuf.clear(); + clearPredictors(); bufferedPacks = 0; myMeta.toFile(config->getString("input") + ".dtsh"); for (std::map::iterator it = myMeta.tracks.begin(); @@ -571,24 +571,27 @@ namespace Mist{ void InputEBML::seek(int seekTime){ wantBlocks = true; - packBuf.clear(); + clearPredictors(); bufferedPacks = 0; uint64_t mainTrack = getMainSelectedTrack(); DTSC::Track Trk = myMeta.tracks[mainTrack]; bool isVideo = (Trk.type == "video"); uint64_t seekPos = Trk.keys[0].getBpos(); // Replay the parts of the previous keyframe, so the timestaps match up - uint64_t partCount = 0; - for (unsigned int i = 0; i < Trk.keys.size(); i++){ - if (Trk.keys[i].getTime() > seekTime){ - break; - } - partCount += Trk.keys[i].getParts(); - DONTEVEN_MSG("Seeking to %lu, found %llu...", seekTime, Trk.keys[i].getTime()); + for (unsigned int i = 1; i < Trk.keys.size(); i++){ + if (Trk.keys[i].getTime() > seekTime){break;} seekPos = Trk.keys[i].getBpos(); } Util::fseek(inFile, seekPos, SEEK_SET); } + ///Flushes all trackPredictors without deleting permanent data from them. + void InputEBML::clearPredictors(){ + if (!packBuf.size()){return;} + for (std::map::iterator it = packBuf.begin(); it != packBuf.end(); ++it){ + it->second.flush(); + } + } + }// namespace Mist diff --git a/src/input/input_ebml.h b/src/input/input_ebml.h index 26f5664e..d1cf2c23 100644 --- a/src/input/input_ebml.h +++ b/src/input/input_ebml.h @@ -75,17 +75,42 @@ namespace Mist{ return p; } if (rem && !p.key){ + uint64_t dispTime = p.time; + if (p.time + frameOffset < lastTime + smallestFrame){ + uint32_t shift = (uint32_t)((((lastTime+smallestFrame)-(p.time+frameOffset)) + (smallestFrame-1)) / smallestFrame) * smallestFrame; + if (shift < smallestFrame){shift = smallestFrame;} + VERYHIGH_MSG("Offset negative, shifting original time forward by %" PRIu32, shift); + p.time += shift; + } p.offset = p.time - (lastTime + smallestFrame) + frameOffset; if (p.offset > maxOffset){ uint64_t diff = p.offset - maxOffset; + VERYHIGH_MSG("Shifting forward %" PRIu64 "ms (maxOffset reached: %" PRIu64 " > %" PRIu64 ")", diff, p.offset, maxOffset); p.offset -= diff; lastTime += diff; } + p.time = (lastTime + smallestFrame); //If we calculate an offset less than a frame away, //we assume it's just time stamp drift due to lack of precision. - p.time = (lastTime + smallestFrame); + p.offset = ((uint32_t)((p.offset + (smallestFrame/2)) / smallestFrame)) * smallestFrame; + //Shift the time forward if needed, but never backward + if (p.offset + p.time < dispTime){ + VERYHIGH_MSG("Shifting forward %" PRIu64 "ms (time drift)", dispTime - (p.offset + p.time)); + p.time += dispTime - (p.offset + p.time); + } }else{ if (!frameOffsetKnown){ + //Check the first few timestamps against each other, find the smallest distance. + for (uint64_t i = 1; i < ctr; ++i){ + uint64_t t1 = pkts[i%PKT_COUNT].time; + for (uint64_t j = 0; j < ctr; ++j){ + if (i == j){continue;} + uint64_t t2 = pkts[j%PKT_COUNT].time; + uint64_t tDiff = (t1::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){ @@ -110,7 +109,7 @@ namespace Mist{ EXTREME_MSG("Cluster: %llu - %llu (%lu/%lu) = %llu", currentClusterTime, newClusterTime, fragIndice, Trk.fragments.size(), clusterSize(currentClusterTime, newClusterTime)); }else{ //In live, clusters are aligned with the lookAhead time - newClusterTime = currentClusterTime+needsLookAhead; + newClusterTime = currentClusterTime+(needsLookAhead?needsLookAhead:1); } EBML::sendElemHead(myConn, EBML::EID_CLUSTER, clusterSize(currentClusterTime, newClusterTime)); EBML::sendElemUInt(myConn, EBML::EID_TIMECODE, currentClusterTime);