Significant speed boost to all TS-based outputs

This commit is contained in:
Thulinma 2016-10-11 16:38:56 +02:00
parent 8f6d75e51e
commit 15def0eaec
3 changed files with 93 additions and 81 deletions

View file

@ -229,8 +229,8 @@ namespace Mist {
H.StartResponse(H, myConn, VLCworkaround); H.StartResponse(H, myConn, VLCworkaround);
//we assume whole fragments - but timestamps may be altered at will //we assume whole fragments - but timestamps may be altered at will
uint32_t fragIndice = Trk.timeToFragnum(from); uint32_t fragIndice = Trk.timeToFragnum(from);
contCounters[0] = Trk.missedFrags + fragIndice; //PAT continuity counter contPAT = Trk.missedFrags + fragIndice; //PAT continuity counter
contCounters[4096] = Trk.missedFrags + fragIndice; //PMT continuity counter contPMT = Trk.missedFrags + fragIndice; //PMT continuity counter
packCounter = 0; packCounter = 0;
parseData = true; parseData = true;
wantRequest = false; wantRequest = false;

View file

@ -11,73 +11,90 @@ namespace Mist {
appleCompat=false; appleCompat=false;
} }
void TSOutput::fillPacket(const char * data, const size_t dataLen){ void TSOutput::fillPacket(char const * data, size_t dataLen, bool & firstPack, bool video, bool keyframe, uint32_t pkgPid, int & contPkg){
do {
if (!packData.getBytesFree()){ if (!packData.getBytesFree()){
///\todo only resend the PAT/PMT for HLS if ( (sendRepeatingHeaders && packCounter % 42 == 0) || !packCounter){
if ( (sendRepeatingHeaders && packCounter % 42 == 0) || !packCounter){ TS::Packet tmpPack;
TS::Packet tmpPack; tmpPack.FromPointer(TS::PAT);
tmpPack.FromPointer(TS::PAT); tmpPack.setContinuityCounter(++contPAT);
tmpPack.setContinuityCounter(++contCounters[0]); sendTS(tmpPack.checkAndGetBuffer());
sendTS(tmpPack.checkAndGetBuffer()); sendTS(TS::createPMT(selectedTracks, myMeta, ++contPMT));
sendTS(TS::createPMT(selectedTracks, myMeta, ++contCounters[4096])); packCounter += 2;
packCounter += 2;
}
sendTS(packData.checkAndGetBuffer());
packCounter ++;
packData.clear();
}
if (!dataLen){return;}
if (packData.getBytesFree() == 184){
packData.clear();
packData.setPID(255 + thisPacket.getTrackId());
packData.setContinuityCounter(++contCounters[packData.getPID()]);
if (first[thisPacket.getTrackId()]){
packData.setUnitStart(1);
packData.setDiscontinuity(true);
if (myMeta.tracks[thisPacket.getTrackId()].type == "video"){
if (thisPacket.getInt("keyframe")){
packData.setRandomAccess(true);
packData.setESPriority(true);
}
packData.setPCR(thisPacket.getTime() * 27000);
} }
first[thisPacket.getTrackId()] = false; sendTS(packData.checkAndGetBuffer());
packCounter ++;
packData.clear();
} }
}
if (!dataLen){return;}
int tmp = packData.fillFree(data, dataLen);
if (tmp != dataLen){ if (packData.getBytesFree() == 184){
return fillPacket(data+tmp, dataLen-tmp); packData.clear();
} packData.setPID(pkgPid);
packData.setContinuityCounter(++contPkg);
if (firstPack){
packData.setUnitStart(1);
packData.setDiscontinuity(true);
if (video){
if (keyframe){
packData.setRandomAccess(true);
packData.setESPriority(true);
}
packData.setPCR(thisPacket.getTime() * 27000);
}
firstPack = false;
}
}
int tmp = packData.fillFree(data, dataLen);
data += tmp;
dataLen -= tmp;
} while(dataLen);
} }
void TSOutput::sendNext(){ void TSOutput::sendNext(){
first[thisPacket.getTrackId()] = true; //Get ready some data to speed up accesses
uint32_t trackId = thisPacket.getTrackId();
DTSC::Track & Trk = myMeta.tracks[trackId];
bool & firstPack = first[trackId];
uint32_t pkgPid = 255 + trackId;
int & contPkg = contCounters[pkgPid];
uint64_t packTime = thisPacket.getTime();
bool video = (Trk.type == "video");
bool keyframe = thisPacket.getInt("keyframe");
firstPack = true;
char * dataPointer = 0; char * dataPointer = 0;
unsigned int dataLen = 0; unsigned int dataLen = 0;
thisPacket.getString("data", dataPointer, dataLen); //data thisPacket.getString("data", dataPointer, dataLen); //data
if (thisPacket.getTime() >= until){ //this if should only trigger for HLS if (packTime >= until){ //this if should only trigger for HLS
stop(); stop();
wantRequest = true; wantRequest = true;
parseData = false; parseData = false;
sendTS("",0); sendTS("",0);
return; return;
} }
//apple compatibility timestamp correction
if (appleCompat){
packTime -= ts_from;
if (Trk.type == "audio"){
packTime = 0;
}
}
packTime *= 90;
std::string bs; std::string bs;
//prepare bufferstring //prepare bufferstring
if (myMeta.tracks[thisPacket.getTrackId()].type == "video"){ if (video){
unsigned int extraSize = 0; unsigned int extraSize = 0;
//dataPointer[4] & 0x1f is used to check if this should be done later: fillPacket("\000\000\000\001\011\360", 6); //dataPointer[4] & 0x1f is used to check if this should be done later: fillPacket("\000\000\000\001\011\360", 6);
if (myMeta.tracks[thisPacket.getTrackId()].codec == "H264" && (dataPointer[4] & 0x1f) != 0x09){ if (Trk.codec == "H264" && (dataPointer[4] & 0x1f) != 0x09){
extraSize += 6; extraSize += 6;
} }
if (thisPacket.getInt("keyframe")){ if (keyframe){
if (myMeta.tracks[thisPacket.getTrackId()].codec == "H264"){ if (Trk.codec == "H264"){
if (!haveAvcc){ if (!haveAvcc){
avccbox.setPayload(myMeta.tracks[thisPacket.getTrackId()].init); avccbox.setPayload(Trk.init);
haveAvcc = true; haveAvcc = true;
} }
bs = avccbox.asAnnexB(); bs = avccbox.asAnnexB();
@ -91,30 +108,29 @@ namespace Mist {
unsigned int ThisNaluSize = 0; unsigned int ThisNaluSize = 0;
unsigned int i = 0; unsigned int i = 0;
unsigned int nalLead = 0; unsigned int nalLead = 0;
uint64_t offset = thisPacket.getInt("offset") * 90;
while (currPack <= splitCount){ while (currPack <= splitCount){
unsigned int alreadySent = 0; unsigned int alreadySent = 0;
long long unsigned int tempTime = thisPacket.getTime(); bs = TS::Packet::getPESVideoLeadIn((currPack != splitCount ? watKunnenWeIn1Ding : dataLen+extraSize - currPack*watKunnenWeIn1Ding), packTime, offset, !currPack);
if (appleCompat){tempTime -= ts_from;} fillPacket(bs.data(), bs.size(), firstPack, video, keyframe, pkgPid, contPkg);
bs = TS::Packet::getPESVideoLeadIn((currPack != splitCount ? watKunnenWeIn1Ding : dataLen+extraSize - currPack*watKunnenWeIn1Ding), tempTime * 90, thisPacket.getInt("offset") * 90, !currPack);
fillPacket(bs.data(), bs.size());
if (!currPack){ if (!currPack){
if (myMeta.tracks[thisPacket.getTrackId()].codec == "H264" && (dataPointer[4] & 0x1f) != 0x09){ if (Trk.codec == "H264" && (dataPointer[4] & 0x1f) != 0x09){
//End of previous nal unit, if not already present //End of previous nal unit, if not already present
fillPacket("\000\000\000\001\011\360", 6); fillPacket("\000\000\000\001\011\360", 6, firstPack, video, keyframe, pkgPid, contPkg);
alreadySent += 6; alreadySent += 6;
} }
if (thisPacket.getInt("keyframe")){ if (keyframe){
if (myMeta.tracks[thisPacket.getTrackId()].codec == "H264"){ if (Trk.codec == "H264"){
bs = avccbox.asAnnexB(); bs = avccbox.asAnnexB();
fillPacket(bs.data(), bs.size()); fillPacket(bs.data(), bs.size(), firstPack, video, keyframe, pkgPid, contPkg);
alreadySent += bs.size(); alreadySent += bs.size();
} }
} }
} }
while (i + 4 < (unsigned int)dataLen){ while (i + 4 < (unsigned int)dataLen){
if (nalLead){ if (nalLead){
fillPacket("\000\000\000\001"+4-nalLead,nalLead); fillPacket("\000\000\000\001"+4-nalLead,nalLead, firstPack, video, keyframe, pkgPid, contPkg);
i += nalLead; i += nalLead;
alreadySent += nalLead; alreadySent += nalLead;
nalLead = 0; nalLead = 0;
@ -127,57 +143,51 @@ namespace Mist {
} }
if (alreadySent + 4 > watKunnenWeIn1Ding){ if (alreadySent + 4 > watKunnenWeIn1Ding){
nalLead = 4 - (watKunnenWeIn1Ding-alreadySent); nalLead = 4 - (watKunnenWeIn1Ding-alreadySent);
fillPacket("\000\000\000\001",watKunnenWeIn1Ding-alreadySent); fillPacket("\000\000\000\001",watKunnenWeIn1Ding-alreadySent, firstPack, video, keyframe, pkgPid, contPkg);
i += watKunnenWeIn1Ding-alreadySent; i += watKunnenWeIn1Ding-alreadySent;
alreadySent += watKunnenWeIn1Ding-alreadySent; alreadySent += watKunnenWeIn1Ding-alreadySent;
}else{ }else{
fillPacket("\000\000\000\001",4); fillPacket("\000\000\000\001",4, firstPack, video, keyframe, pkgPid, contPkg);
alreadySent += 4; alreadySent += 4;
i += 4; i += 4;
} }
} }
if (alreadySent + ThisNaluSize > watKunnenWeIn1Ding){ if (alreadySent + ThisNaluSize > watKunnenWeIn1Ding){
fillPacket(dataPointer+i,watKunnenWeIn1Ding-alreadySent); fillPacket(dataPointer+i,watKunnenWeIn1Ding-alreadySent, firstPack, video, keyframe, pkgPid, contPkg);
i += watKunnenWeIn1Ding-alreadySent; i += watKunnenWeIn1Ding-alreadySent;
ThisNaluSize -= watKunnenWeIn1Ding-alreadySent; ThisNaluSize -= watKunnenWeIn1Ding-alreadySent;
alreadySent += watKunnenWeIn1Ding-alreadySent; alreadySent += watKunnenWeIn1Ding-alreadySent;
}else{ }else{
fillPacket(dataPointer+i,ThisNaluSize); fillPacket(dataPointer+i,ThisNaluSize, firstPack, video, keyframe, pkgPid, contPkg);
alreadySent += ThisNaluSize; alreadySent += ThisNaluSize;
i += ThisNaluSize; i += ThisNaluSize;
ThisNaluSize = 0; ThisNaluSize = 0;
} }
if (alreadySent == watKunnenWeIn1Ding){ if (alreadySent == watKunnenWeIn1Ding){
packData.addStuffing(); packData.addStuffing();
fillPacket(0, 0); fillPacket(0, 0, firstPack, video, keyframe, pkgPid, contPkg);
first[thisPacket.getTrackId()] = true; firstPack = true;
break; break;
} }
} }
currPack++; currPack++;
} }
}else if (myMeta.tracks[thisPacket.getTrackId()].type == "audio"){ }else if (Trk.type == "audio"){
long unsigned int tempLen = dataLen; long unsigned int tempLen = dataLen;
if ( myMeta.tracks[thisPacket.getTrackId()].codec == "AAC"){ if (Trk.codec == "AAC"){
tempLen += 7; tempLen += 7;
} }
long long unsigned int tempTime; bs = TS::Packet::getPESAudioLeadIn(tempLen, packTime);// myMeta.tracks[thisPacket.getTrackId()].rate / 1000 );
if (appleCompat){ fillPacket(bs.data(), bs.size(), firstPack, video, keyframe, pkgPid, contPkg);
tempTime = 0;// myMeta.tracks[thisPacket.getTrackId()].rate / 1000; if (Trk.codec == "AAC"){
}else{ bs = TS::getAudioHeader(dataLen, Trk.init);
tempTime = thisPacket.getTime() * 90; fillPacket(bs.data(), bs.size(), firstPack, video, keyframe, pkgPid, contPkg);
} }
bs = TS::Packet::getPESAudioLeadIn(tempLen, tempTime);// myMeta.tracks[thisPacket.getTrackId()].rate / 1000 ); fillPacket(dataPointer,dataLen, firstPack, video, keyframe, pkgPid, contPkg);
fillPacket(bs.data(), bs.size());
if (myMeta.tracks[thisPacket.getTrackId()].codec == "AAC"){
bs = TS::getAudioHeader(dataLen, myMeta.tracks[thisPacket.getTrackId()].init);
fillPacket(bs.data(), bs.size());
}
fillPacket(dataPointer,dataLen);
} }
if (packData.getBytesFree() < 184){ if (packData.getBytesFree() < 184){
packData.addStuffing(); packData.addStuffing();
fillPacket(0, 0); fillPacket(0, 0, firstPack, video, keyframe, pkgPid, contPkg);
} }
} }
} }

View file

@ -16,10 +16,12 @@ namespace Mist {
virtual ~TSOutput(){}; virtual ~TSOutput(){};
void sendNext(); void sendNext();
virtual void sendTS(const char * tsData, unsigned int len=188){}; virtual void sendTS(const char * tsData, unsigned int len=188){};
void fillPacket(const char * data, const size_t dataLen); void fillPacket(char const * data, size_t dataLen, bool & firstPack, bool video, bool keyframe, uint32_t pkgPid, int & contPkg);
protected: protected:
std::map<unsigned int, bool> first; std::map<unsigned int, bool> first;
std::map<unsigned int, int> contCounters; std::map<unsigned int, int> contCounters;
int contPAT;
int contPMT;
unsigned int packCounter; ///\todo update constructors? unsigned int packCounter; ///\todo update constructors?
TS::Packet packData; TS::Packet packData;
bool haveAvcc; bool haveAvcc;