EBML fix for non-static GOP sizes

This commit is contained in:
Thulinma 2018-10-09 17:33:17 +02:00
parent 3a3498f17c
commit a53fd5fa63
2 changed files with 70 additions and 34 deletions

View file

@ -40,6 +40,7 @@ namespace Mist{
lastClusterBPos = 0; lastClusterBPos = 0;
lastClusterTime = 0; lastClusterTime = 0;
bufferedPacks = 0; bufferedPacks = 0;
wantBlocks = true;
} }
std::string ASStoSRT(const char * ptr, uint32_t len){ std::string ASStoSRT(const char * ptr, uint32_t len){
@ -349,6 +350,15 @@ namespace Mist{
bool isVideo = (Trk.type == "video"); bool isVideo = (Trk.type == "video");
bool isAudio = (Trk.type == "audio"); bool isAudio = (Trk.type == "audio");
bool isASS = (Trk.codec == "subtitle" && Trk.init.size()); bool isASS = (Trk.codec == "subtitle" && Trk.init.size());
//If this is a new video keyframe, flush the corresponding trackPredictor
if (isVideo && B.isKeyframe()){
while (TP.hasPackets(true)){
packetData &C = TP.getPacketData(true);
myMeta.update(C.time, C.offset, C.track, C.dsize, C.bpos, C.key);
TP.remove();
}
TP.flush();
}
for (uint64_t frameNo = 0; frameNo < B.getFrameCount(); ++frameNo){ for (uint64_t frameNo = 0; frameNo < B.getFrameCount(); ++frameNo){
if (frameNo){ if (frameNo){
if (Trk.codec == "AAC"){ if (Trk.codec == "AAC"){
@ -463,28 +473,32 @@ namespace Mist{
} }
} }
EBML::Block B; EBML::Block B;
do{ if (wantBlocks){
if (!readElement()){ do{
// Make sure we empty our buffer first if (!readElement()){
if (bufferedPacks && packBuf.size()){ // Make sure we empty our buffer first
for (std::map<uint64_t, trackPredictor>::iterator it = packBuf.begin(); if (bufferedPacks && packBuf.size()){
it != packBuf.end(); ++it){ for (std::map<uint64_t, trackPredictor>::iterator it = packBuf.begin();
trackPredictor &TP = it->second; it != packBuf.end(); ++it){
if (TP.hasPackets(true)){ trackPredictor &TP = it->second;
packetData &C = TP.getPacketData(myMeta.tracks[it->first].type == "video"); if (TP.hasPackets(true)){
fillPacket(C); packetData &C = TP.getPacketData(myMeta.tracks[it->first].type == "video");
TP.remove(); fillPacket(C);
--bufferedPacks; TP.remove();
return; --bufferedPacks;
return;
}
} }
} }
// No more buffer? Set to empty
thisPacket.null();
return;
} }
// No more buffer? Set to empty B = EBML::Block(ptr);
thisPacket.null(); }while (!B || B.getType() != EBML::ELEM_BLOCK || !selectedTracks.count(B.getTrackNum()));
return; }else{
}
B = EBML::Block(ptr); B = EBML::Block(ptr);
}while (!B || B.getType() != EBML::ELEM_BLOCK || !selectedTracks.count(B.getTrackNum())); }
uint64_t tNum = B.getTrackNum(); uint64_t tNum = B.getTrackNum();
uint64_t newTime = lastClusterTime + B.getTimecode(); uint64_t newTime = lastClusterTime + B.getTimecode();
@ -493,6 +507,24 @@ namespace Mist{
bool isVideo = (Trk.type == "video"); bool isVideo = (Trk.type == "video");
bool isAudio = (Trk.type == "audio"); bool isAudio = (Trk.type == "audio");
bool isASS = (Trk.codec == "subtitle" && Trk.init.size()); bool isASS = (Trk.codec == "subtitle" && Trk.init.size());
//If this is a new video keyframe, flush the corresponding trackPredictor
if (isVideo && B.isKeyframe() && bufferedPacks){
if (TP.hasPackets(true)){
wantBlocks = false;
packetData &C = TP.getPacketData(true);
fillPacket(C);
TP.remove();
--bufferedPacks;
return;
}
}
if (isVideo && B.isKeyframe()){
TP.flush();
}
wantBlocks = true;
for (uint64_t frameNo = 0; frameNo < B.getFrameCount(); ++frameNo){ for (uint64_t frameNo = 0; frameNo < B.getFrameCount(); ++frameNo){
if (frameNo){ if (frameNo){
if (Trk.codec == "AAC"){ if (Trk.codec == "AAC"){
@ -531,6 +563,7 @@ namespace Mist{
} }
void InputEBML::seek(int seekTime){ void InputEBML::seek(int seekTime){
wantBlocks = true;
packBuf.clear(); packBuf.clear();
bufferedPacks = 0; bufferedPacks = 0;
uint64_t mainTrack = getMainSelectedTrack(); uint64_t mainTrack = getMainSelectedTrack();
@ -541,17 +574,6 @@ namespace Mist{
uint64_t partCount = 0; uint64_t partCount = 0;
for (unsigned int i = 0; i < Trk.keys.size(); i++){ for (unsigned int i = 0; i < Trk.keys.size(); i++){
if (Trk.keys[i].getTime() > seekTime){ if (Trk.keys[i].getTime() > seekTime){
if (i > 1){
partCount -= Trk.keys[i-1].getParts() + Trk.keys[i-2].getParts();
uint64_t partEnd = partCount + Trk.keys[i-2].getParts();
uint64_t partTime = Trk.keys[i-2].getTime();
for (uint64_t prt = partCount; prt < partEnd; ++prt){
INSANE_MSG("Replay part %llu, timestamp: %llu+%llu", prt, partTime, Trk.parts[prt].getOffset());
packBuf[mainTrack].add(partTime, Trk.parts[prt].getOffset(), mainTrack, 0, 0, false, isVideo, (void *)0);
packBuf[mainTrack].remove();
partTime += Trk.parts[prt].getDuration();
}
}
break; break;
} }
partCount += Trk.keys[i].getParts(); partCount += Trk.keys[i].getParts();

View file

@ -40,15 +40,13 @@ namespace Mist{
class trackPredictor{ class trackPredictor{
public: public:
packetData pkts[PKT_COUNT]; packetData pkts[PKT_COUNT];
uint64_t frameOffset;
uint16_t smallestFrame; uint16_t smallestFrame;
uint64_t lastTime; uint64_t lastTime;
uint64_t ctr; uint64_t ctr;
uint64_t rem; uint64_t rem;
trackPredictor(){ trackPredictor(){
smallestFrame = 0; flush();
lastTime = 0;
ctr = 0;
rem = 0;
} }
bool hasPackets(bool finished = false){ bool hasPackets(bool finished = false){
if (finished){ if (finished){
@ -57,6 +55,14 @@ namespace Mist{
return (ctr - rem > 12); return (ctr - rem > 12);
} }
} }
/// Clears all internal values, for reuse as-new.
void flush(){
frameOffset = 0;
smallestFrame = 0;
lastTime = 0;
ctr = 0;
rem = 0;
}
packetData & getPacketData(bool mustCalcOffsets){ packetData & getPacketData(bool mustCalcOffsets){
frameOffsetKnown = true; frameOffsetKnown = true;
//grab the next packet to output //grab the next packet to output
@ -74,13 +80,20 @@ namespace Mist{
//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.time = (lastTime + smallestFrame);
}else{ }else{
p.offset = maxEBMLFrameOffset; p.time -= frameOffset?frameOffset + smallestFrame:0;
p.offset = maxEBMLFrameOffset + frameOffset + smallestFrame;
} }
} }
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);
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 (!rem && ctr && packTime < pkts[0].time){
frameOffset = pkts[0].time - packTime;
INSANE_MSG("Setting frameOffset to %llu", frameOffset);
}
if (isVideo && ctr && ctr >= rem){ if (isVideo && ctr && ctr >= rem){
int32_t currOffset = packTime - pkts[(ctr-1)%PKT_COUNT].time; int32_t currOffset = packTime - pkts[(ctr-1)%PKT_COUNT].time;
if (currOffset < 0){currOffset *= -1;} if (currOffset < 0){currOffset *= -1;}
@ -131,6 +144,7 @@ namespace Mist{
bool openStreamSource(){return true;} bool openStreamSource(){return true;}
bool needHeader(){return needsLock() && !readExistingHeader();} bool needHeader(){return needsLock() && !readExistingHeader();}
double timeScale; double timeScale;
bool wantBlocks;
}; };
} }