EBML fix for non-static GOP sizes
This commit is contained in:
parent
3a3498f17c
commit
a53fd5fa63
2 changed files with 70 additions and 34 deletions
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue