EBML input/output improvements and fixes

This commit is contained in:
Thulinma 2019-05-02 18:25:07 +02:00
parent 84f9463059
commit 92d59befa6
3 changed files with 44 additions and 15 deletions

View file

@ -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<unsigned int, DTSC::Track>::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<uint64_t, trackPredictor>::iterator it = packBuf.begin(); it != packBuf.end(); ++it){
it->second.flush();
}
}
}// namespace Mist

View file

@ -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<t2)?(t2-t1):(t1-t2);
if (tDiff < smallestFrame){smallestFrame = tDiff;}
}
}
//Cool, now we're pretty sure we know the frame rate. Let's calculate some offsets.
for (uint64_t i = 1; i < ctr; ++i){
uint64_t timeDiff = pkts[i%PKT_COUNT].time - lowestTime;
uint64_t timeExpt = smallestFrame*i;
@ -97,10 +122,11 @@ namespace Mist{
}
}
maxOffset += frameOffset;
//Print for debugging purposes, and consider them gospel from here on forward. Yay!
HIGH_MSG("smallestFrame=%" PRIu16 ", frameOffset=%" PRIu64 ", maxOffset=%" PRIu64, smallestFrame, frameOffset, maxOffset);
frameOffsetKnown = true;
}
p.offset = frameOffset;
p.offset = ((uint32_t)((frameOffset + (smallestFrame/2)) / smallestFrame)) * smallestFrame;
}
lastTime = p.time;
INSANE_MSG("Outputting%s %llu+%llu (#%llu, Max=%llu), display at %llu", (p.key?"KEY":""), p.time, p.offset, rem, maxOffset, p.time+p.offset);
@ -131,6 +157,7 @@ namespace Mist{
bool readElement();
void getNext(bool smart = true);
void seek(int seekTime);
void clearPredictors();
FILE *inFile;
Util::ResizeablePointer ptr;
bool readingMinimal;

View file

@ -45,8 +45,8 @@ namespace Mist{
capa["methods"][0u]["handler"] = "http";
capa["methods"][0u]["type"] = "html5/video/webm";
capa["methods"][0u]["priority"] = 9;
//EBML will only work with VP8/VP9/Opus except on Chrome
JSON::Value blacklistNonChrome = JSON::fromString("[[\"blacklist\"], [\"whitelist\",[\"Chrome\",\"Chromium\"]], [\"blacklist\",[\"Edge\",\"OPR/\"]], [\"blacklist\",[\"Android\"]]]");
//Browsers only support VP8/VP9/Opus codecs, except Chrome which is more lenient.
JSON::Value blacklistNonChrome = JSON::fromString("[[\"blacklist\", [\"Mozilla/\"]], [\"whitelist\",[\"Chrome\",\"Chromium\"]], [\"blacklist\",[\"Edge\",\"OPR/\"]], [\"blacklist\",[\"Android\"]]]");
capa["exceptions"]["codec:H264"] = blacklistNonChrome;
capa["exceptions"]["codec:HEVC"] = blacklistNonChrome;
capa["exceptions"]["codec:theora"] = blacklistNonChrome;
@ -66,7 +66,6 @@ namespace Mist{
/// Calculates the size of a Cluster (contents only) and returns it.
/// Bases the calculation on the currently selected tracks and the given start/end time for the cluster.
uint32_t OutEBML::clusterSize(uint64_t start, uint64_t end){
if (start <= end){end = start+1;}
uint32_t sendLen = EBML::sizeElemUInt(EBML::EID_TIMECODE, start);
for (std::set<long unsigned int>::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);