EBML input/output improvements and fixes
This commit is contained in:
parent
84f9463059
commit
92d59befa6
3 changed files with 44 additions and 15 deletions
|
@ -407,7 +407,7 @@ namespace Mist{
|
||||||
|
|
||||||
bench = Util::getMicros(bench);
|
bench = Util::getMicros(bench);
|
||||||
INFO_MSG("Header generated in %llu ms", bench / 1000);
|
INFO_MSG("Header generated in %llu ms", bench / 1000);
|
||||||
packBuf.clear();
|
clearPredictors();
|
||||||
bufferedPacks = 0;
|
bufferedPacks = 0;
|
||||||
myMeta.toFile(config->getString("input") + ".dtsh");
|
myMeta.toFile(config->getString("input") + ".dtsh");
|
||||||
for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin();
|
for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin();
|
||||||
|
@ -571,24 +571,27 @@ namespace Mist{
|
||||||
|
|
||||||
void InputEBML::seek(int seekTime){
|
void InputEBML::seek(int seekTime){
|
||||||
wantBlocks = true;
|
wantBlocks = true;
|
||||||
packBuf.clear();
|
clearPredictors();
|
||||||
bufferedPacks = 0;
|
bufferedPacks = 0;
|
||||||
uint64_t mainTrack = getMainSelectedTrack();
|
uint64_t mainTrack = getMainSelectedTrack();
|
||||||
DTSC::Track Trk = myMeta.tracks[mainTrack];
|
DTSC::Track Trk = myMeta.tracks[mainTrack];
|
||||||
bool isVideo = (Trk.type == "video");
|
bool isVideo = (Trk.type == "video");
|
||||||
uint64_t seekPos = Trk.keys[0].getBpos();
|
uint64_t seekPos = Trk.keys[0].getBpos();
|
||||||
// Replay the parts of the previous keyframe, so the timestaps match up
|
// Replay the parts of the previous keyframe, so the timestaps match up
|
||||||
uint64_t partCount = 0;
|
for (unsigned int i = 1; i < Trk.keys.size(); i++){
|
||||||
for (unsigned int i = 0; i < Trk.keys.size(); i++){
|
if (Trk.keys[i].getTime() > seekTime){break;}
|
||||||
if (Trk.keys[i].getTime() > seekTime){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
partCount += Trk.keys[i].getParts();
|
|
||||||
DONTEVEN_MSG("Seeking to %lu, found %llu...", seekTime, Trk.keys[i].getTime());
|
|
||||||
seekPos = Trk.keys[i].getBpos();
|
seekPos = Trk.keys[i].getBpos();
|
||||||
}
|
}
|
||||||
Util::fseek(inFile, seekPos, SEEK_SET);
|
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
|
}// namespace Mist
|
||||||
|
|
||||||
|
|
|
@ -75,17 +75,42 @@ namespace Mist{
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
if (rem && !p.key){
|
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;
|
p.offset = p.time - (lastTime + smallestFrame) + frameOffset;
|
||||||
if (p.offset > maxOffset){
|
if (p.offset > maxOffset){
|
||||||
uint64_t diff = 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;
|
p.offset -= diff;
|
||||||
lastTime += diff;
|
lastTime += diff;
|
||||||
}
|
}
|
||||||
|
p.time = (lastTime + smallestFrame);
|
||||||
//If we calculate an offset less than a frame away,
|
//If we calculate an offset less than a frame away,
|
||||||
//we assume it's just time stamp drift due to lack of precision.
|
//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{
|
}else{
|
||||||
if (!frameOffsetKnown){
|
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){
|
for (uint64_t i = 1; i < ctr; ++i){
|
||||||
uint64_t timeDiff = pkts[i%PKT_COUNT].time - lowestTime;
|
uint64_t timeDiff = pkts[i%PKT_COUNT].time - lowestTime;
|
||||||
uint64_t timeExpt = smallestFrame*i;
|
uint64_t timeExpt = smallestFrame*i;
|
||||||
|
@ -97,10 +122,11 @@ namespace Mist{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
maxOffset += frameOffset;
|
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);
|
HIGH_MSG("smallestFrame=%" PRIu16 ", frameOffset=%" PRIu64 ", maxOffset=%" PRIu64, smallestFrame, frameOffset, maxOffset);
|
||||||
frameOffsetKnown = true;
|
frameOffsetKnown = true;
|
||||||
}
|
}
|
||||||
p.offset = frameOffset;
|
p.offset = ((uint32_t)((frameOffset + (smallestFrame/2)) / smallestFrame)) * smallestFrame;
|
||||||
}
|
}
|
||||||
lastTime = p.time;
|
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);
|
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();
|
bool readElement();
|
||||||
void getNext(bool smart = true);
|
void getNext(bool smart = true);
|
||||||
void seek(int seekTime);
|
void seek(int seekTime);
|
||||||
|
void clearPredictors();
|
||||||
FILE *inFile;
|
FILE *inFile;
|
||||||
Util::ResizeablePointer ptr;
|
Util::ResizeablePointer ptr;
|
||||||
bool readingMinimal;
|
bool readingMinimal;
|
||||||
|
|
|
@ -45,8 +45,8 @@ namespace Mist{
|
||||||
capa["methods"][0u]["handler"] = "http";
|
capa["methods"][0u]["handler"] = "http";
|
||||||
capa["methods"][0u]["type"] = "html5/video/webm";
|
capa["methods"][0u]["type"] = "html5/video/webm";
|
||||||
capa["methods"][0u]["priority"] = 9;
|
capa["methods"][0u]["priority"] = 9;
|
||||||
//EBML will only work with VP8/VP9/Opus except on Chrome
|
//Browsers only support VP8/VP9/Opus codecs, except Chrome which is more lenient.
|
||||||
JSON::Value blacklistNonChrome = JSON::fromString("[[\"blacklist\"], [\"whitelist\",[\"Chrome\",\"Chromium\"]], [\"blacklist\",[\"Edge\",\"OPR/\"]], [\"blacklist\",[\"Android\"]]]");
|
JSON::Value blacklistNonChrome = JSON::fromString("[[\"blacklist\", [\"Mozilla/\"]], [\"whitelist\",[\"Chrome\",\"Chromium\"]], [\"blacklist\",[\"Edge\",\"OPR/\"]], [\"blacklist\",[\"Android\"]]]");
|
||||||
capa["exceptions"]["codec:H264"] = blacklistNonChrome;
|
capa["exceptions"]["codec:H264"] = blacklistNonChrome;
|
||||||
capa["exceptions"]["codec:HEVC"] = blacklistNonChrome;
|
capa["exceptions"]["codec:HEVC"] = blacklistNonChrome;
|
||||||
capa["exceptions"]["codec:theora"] = blacklistNonChrome;
|
capa["exceptions"]["codec:theora"] = blacklistNonChrome;
|
||||||
|
@ -66,7 +66,6 @@ namespace Mist{
|
||||||
/// Calculates the size of a Cluster (contents only) and returns it.
|
/// 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.
|
/// 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){
|
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);
|
uint32_t sendLen = EBML::sizeElemUInt(EBML::EID_TIMECODE, start);
|
||||||
for (std::set<long unsigned int>::iterator it = selectedTracks.begin();
|
for (std::set<long unsigned int>::iterator it = selectedTracks.begin();
|
||||||
it != selectedTracks.end(); it++){
|
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));
|
EXTREME_MSG("Cluster: %llu - %llu (%lu/%lu) = %llu", currentClusterTime, newClusterTime, fragIndice, Trk.fragments.size(), clusterSize(currentClusterTime, newClusterTime));
|
||||||
}else{
|
}else{
|
||||||
//In live, clusters are aligned with the lookAhead time
|
//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::sendElemHead(myConn, EBML::EID_CLUSTER, clusterSize(currentClusterTime, newClusterTime));
|
||||||
EBML::sendElemUInt(myConn, EBML::EID_TIMECODE, currentClusterTime);
|
EBML::sendElemUInt(myConn, EBML::EID_TIMECODE, currentClusterTime);
|
||||||
|
|
Loading…
Add table
Reference in a new issue