EBML input fixup

This commit is contained in:
Thulinma 2019-05-01 10:45:57 +02:00
parent 320c8ab29f
commit 61bb14a368
2 changed files with 47 additions and 61 deletions

View file

@ -5,9 +5,6 @@
namespace Mist{ namespace Mist{
uint16_t maxEBMLFrameOffset = 0;
bool frameOffsetKnown = false;
InputEBML::InputEBML(Util::Config *cfg) : Input(cfg){ InputEBML::InputEBML(Util::Config *cfg) : Input(cfg){
timeScale = 1.0; timeScale = 1.0;
capa["name"] = "EBML"; capa["name"] = "EBML";
@ -161,10 +158,6 @@ namespace Mist{
if (myMeta.inputLocalVars.isMember("timescale")){ if (myMeta.inputLocalVars.isMember("timescale")){
timeScale = ((double)myMeta.inputLocalVars["timescale"].asInt()) / 1000000.0; timeScale = ((double)myMeta.inputLocalVars["timescale"].asInt()) / 1000000.0;
} }
if (myMeta.inputLocalVars.isMember("maxframeoffset")){
maxEBMLFrameOffset = myMeta.inputLocalVars["maxframeoffset"].asInt();
frameOffsetKnown = true;
}
return true; return true;
} }
@ -392,8 +385,7 @@ namespace Mist{
B.isKeyframe() && !isAudio, isVideo); B.isKeyframe() && !isAudio, isVideo);
} }
} }
while (TP.hasPackets() && (isVideo || frameOffsetKnown)){ while (TP.hasPackets()){
frameOffsetKnown = true;
packetData &C = TP.getPacketData(isVideo); packetData &C = TP.getPacketData(isVideo);
myMeta.update(C.time, C.offset, C.track, C.dsize, C.bpos, C.key); myMeta.update(C.time, C.offset, C.track, C.dsize, C.bpos, C.key);
TP.remove(); TP.remove();
@ -413,8 +405,6 @@ namespace Mist{
} }
} }
myMeta.inputLocalVars["maxframeoffset"] = maxEBMLFrameOffset;
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(); packBuf.clear();

View file

@ -5,8 +5,6 @@
namespace Mist{ namespace Mist{
extern uint16_t maxEBMLFrameOffset;
extern bool frameOffsetKnown;
#define PKT_COUNT 64 #define PKT_COUNT 64
class packetData{ class packetData{
@ -40,79 +38,77 @@ namespace Mist{
class trackPredictor{ class trackPredictor{
public: public:
packetData pkts[PKT_COUNT]; packetData pkts[PKT_COUNT];
uint64_t frameOffset; uint64_t frameOffset;///The static average offset between transmit time and display time
uint16_t smallestFrame; bool frameOffsetKnown;///Whether the average frame offset is known
uint64_t lastTime; uint16_t smallestFrame;///low-ball estimate of time per frame
uint64_t ctr; uint64_t lastTime;///last send transmit timestamp
uint64_t rem; uint64_t ctr;///ingested frame count
uint64_t rem;///removed frame count
uint64_t maxOffset;///maximum offset for this track
uint64_t lowestTime;///First timestamp to enter the buffer
trackPredictor(){ trackPredictor(){
smallestFrame = 0xFFFF;
frameOffsetKnown = false;
frameOffset = 0;
maxOffset = 0;
flush(); flush();
} }
bool hasPackets(bool finished = false){ bool hasPackets(bool finished = false){
if (finished){ if (finished || frameOffsetKnown){
return (ctr - rem > 0); return (ctr - rem > 0);
}else{ }else{
return frameOffsetKnown ? (ctr - rem > 1) : (ctr - rem > 12); return (ctr - rem > 12);
} }
} }
/// Clears all internal values, for reuse as-new. /// Clears all internal values, for reuse as-new.
void flush(){ void flush(){
frameOffset = 0;
smallestFrame = 0;
lastTime = 0; lastTime = 0;
ctr = 0; ctr = 0;
rem = 0; rem = 0;
lowestTime = 0;
} }
packetData & getPacketData(bool mustCalcOffsets){ packetData & getPacketData(bool mustCalcOffsets){
frameOffsetKnown = true;
//grab the next packet to output //grab the next packet to output
packetData & p = pkts[rem % PKT_COUNT]; packetData & p = pkts[rem % PKT_COUNT];
//Substract the max frame offset, so we know all offsets are positive, no matter what.
//if it's not the first and we're calculating offsets, see if we need an offset
if (!mustCalcOffsets){ if (!mustCalcOffsets){
p.time += maxEBMLFrameOffset; frameOffsetKnown = true;
DONTEVEN_MSG("Outputting %llu + %llu (%llu -> %llu)", p.time, maxEBMLFrameOffset, rem, rem % PKT_COUNT);
return p; return p;
}else{ }
if (rem && !p.key){ if (rem && !p.key){
p.offset = p.time + maxEBMLFrameOffset - (lastTime + smallestFrame); p.offset = p.time - (lastTime + smallestFrame) + frameOffset;
if (p.offset > (maxEBMLFrameOffset + frameOffset + smallestFrame)){ if (p.offset > maxOffset){
uint64_t diff = p.offset - (maxEBMLFrameOffset + frameOffset + smallestFrame); uint64_t diff = p.offset - maxOffset;
p.offset -= diff; p.offset -= diff;
lastTime += diff; lastTime += diff;
}
//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);
}else{
p.time -= frameOffset?frameOffset + smallestFrame:0;
p.offset = maxEBMLFrameOffset + frameOffset + 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);
}else{
if (!frameOffsetKnown){
for (uint64_t i = 1; i < ctr; ++i){
uint64_t timeDiff = pkts[i%PKT_COUNT].time - lowestTime;
uint64_t timeExpt = smallestFrame*i;
if (timeDiff > timeExpt && maxOffset < timeDiff-timeExpt){
maxOffset = timeDiff-timeExpt;
}
if (timeDiff < timeExpt && frameOffset < timeExpt-timeDiff){
frameOffset = timeExpt - timeDiff;
}
}
maxOffset += frameOffset;
HIGH_MSG("smallestFrame=%" PRIu16 ", frameOffset=%" PRIu64 ", maxOffset=%" PRIu64, smallestFrame, frameOffset, maxOffset);
frameOffsetKnown = true;
}
p.offset = frameOffset;
} }
lastTime = p.time; lastTime = p.time;
DONTEVEN_MSG("Outputting%s %llu + %llu, offset %llu (%llu -> %llu), display at %llu", (p.key?" (KEY)":""), p.time, frameOffset, p.offset, rem, rem % PKT_COUNT, 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);
return p; return p;
} }
void add(uint64_t packTime, uint64_t packOffset, uint64_t packTrack, uint64_t packDataSize, uint64_t packBytePos, bool isKeyframe, bool isVideo, void * dataPtr = 0){ void add(uint64_t packTime, uint64_t packOffset, uint64_t packTrack, uint64_t packDataSize, uint64_t packBytePos, bool isKeyframe, bool isVideo, void * dataPtr = 0){
//If no packets have been removed yet and there is more than one packet, calculate frameOffset if (!ctr){lowestTime = packTime;}
if (!rem && ctr && packTime < pkts[0].time){ if (packTime > lowestTime && packTime - lowestTime < smallestFrame){smallestFrame = packTime - lowestTime;}
frameOffset = pkts[0].time - packTime;
INSANE_MSG("Setting frameOffset to %llu", frameOffset);
}
if (isVideo && ctr && ctr >= rem){
int32_t currOffset = packTime - pkts[(ctr-1)%PKT_COUNT].time;
if (!frameOffsetKnown && currOffset < 0 && -currOffset < 8 * smallestFrame &&
-currOffset * 2 > maxEBMLFrameOffset && ctr < PKT_COUNT / 2){
maxEBMLFrameOffset = -currOffset * 2;
INFO_MSG("Max frame offset is now %u", maxEBMLFrameOffset);
}
if (currOffset < 0){currOffset *= -1;}
if (!smallestFrame || currOffset < smallestFrame){
smallestFrame = currOffset;
HIGH_MSG("Smallest frame is now %u", smallestFrame);
}
}
DONTEVEN_MSG("Ingesting %llu (%llu -> %llu)", packTime, ctr, ctr % PKT_COUNT);
pkts[ctr % PKT_COUNT].set(packTime, packOffset, packTrack, packDataSize, packBytePos, isKeyframe, dataPtr); pkts[ctr % PKT_COUNT].set(packTime, packOffset, packTrack, packDataSize, packBytePos, isKeyframe, dataPtr);
++ctr; ++ctr;
if (ctr == PKT_COUNT-1){frameOffsetKnown = true;} if (ctr == PKT_COUNT-1){frameOffsetKnown = true;}