Optimizes to TS outputs.

This commit is contained in:
wouter spruit 2014-08-25 19:23:15 +02:00 committed by Thulinma
parent 286d6cba5c
commit d2821a629e
4 changed files with 154 additions and 102 deletions

View file

@ -112,15 +112,55 @@ namespace Mist {
cfg->addBasicConnectorOptions(capa); cfg->addBasicConnectorOptions(capa);
config = cfg; config = cfg;
} }
//HIER
void OutHLS::fillPacket(bool & first, const char * data, size_t dataLen, char & ContCounter){
if (!PackData.BytesFree()){
HTTP_S.Chunkify(PackData.ToString(), 188, myConn);
PacketNumber ++;
PackData.Clear();
if (PacketNumber % 42 == 0){
HTTP_S.Chunkify(TS::PAT, 188, myConn);
HTTP_S.Chunkify(TS::PMT, 188, myConn);
PacketNumber += 2;
}
}
if (!dataLen){return;}
if (PackData.BytesFree() == 184){
if (myMeta.tracks[currentPacket.getTrackId()].type == "video"){
PackData.PID(0x100);
}else{
PackData.PID(0x101);
}
PackData.ContinuityCounter(ContCounter++);
if (first){
PackData.UnitStart(1);
if (currentPacket.getInt("keyframe")){
PackData.RandomAccess(1);
PackData.PCR(currentPacket.getTime() * 27000);
}
first = false;
}
}
int tmp = PackData.FillFree(data, dataLen);
if (tmp != dataLen){
fillPacket(first, data+tmp, dataLen-tmp, ContCounter);
}
}
void OutHLS::sendNext(){ void OutHLS::sendNext(){
Socket::Buffer ToPack; bool first = true;
char * ContCounter = 0; char * ContCounter = 0;
bool IsKeyFrame = false;
char * dataPointer = 0; char * dataPointer = 0;
unsigned int dataLen = 0; unsigned int dataLen = 0;
currentPacket.getString("data", dataPointer, dataLen); currentPacket.getString("data", dataPointer, dataLen); //data
if (currentPacket.getTime() >= until){ if (currentPacket.getTime() >= until){
DEBUG_MSG(DLVL_DEVEL, "(%d) Done sending fragment", getpid() ); DEBUG_MSG(DLVL_DEVEL, "(%d) Done sending fragment", getpid() );
@ -131,18 +171,23 @@ namespace Mist {
return; return;
} }
//detect packet type, and put converted data into ToPack.
if (myMeta.tracks[currentPacket.getTrackId()].type == "video"){
ToPack.append(TS::Packet::getPESVideoLeadIn(0ul, currentPacket.getTime() * 90));
IsKeyFrame = currentPacket.getInt("keyframe");
if (IsKeyFrame){ std::string bs;
//prepare bufferstring
if (myMeta.tracks[currentPacket.getTrackId()].type == "video"){
bs = TS::Packet::getPESVideoLeadIn(0ul, currentPacket.getTime() * 90);
fillPacket(first, bs.data(), bs.size(), VideoCounter);
if (currentPacket.getInt("keyframe")){
if (!haveAvcc){ if (!haveAvcc){
avccbox.setPayload(myMeta.tracks[currentPacket.getTrackId()].init); avccbox.setPayload(myMeta.tracks[currentPacket.getTrackId()].init);
haveAvcc = true; haveAvcc = true;
} }
ToPack.append(avccbox.asAnnexB()); bs = avccbox.asAnnexB();
fillPacket(first, bs.data(), bs.size(), VideoCounter);
} }
unsigned int i = 0; unsigned int i = 0;
while (i + 4 < (unsigned int)dataLen){ while (i + 4 < (unsigned int)dataLen){
unsigned int ThisNaluSize = (dataPointer[i] << 24) + (dataPointer[i+1] << 16) + (dataPointer[i+2] << 8) + dataPointer[i+3]; unsigned int ThisNaluSize = (dataPointer[i] << 24) + (dataPointer[i+1] << 16) + (dataPointer[i+2] << 8) + dataPointer[i+3];
@ -150,54 +195,33 @@ namespace Mist {
DEBUG_MSG(DLVL_WARN, "Too big NALU detected (%u > %d) - skipping!", ThisNaluSize + i + 4, dataLen); DEBUG_MSG(DLVL_WARN, "Too big NALU detected (%u > %d) - skipping!", ThisNaluSize + i + 4, dataLen);
break; break;
} }
ToPack.append("\000\000\000\001", 4); fillPacket(first, "\000\000\000\001",4, VideoCounter);
i += 4; fillPacket(first, dataPointer+i+4,ThisNaluSize, VideoCounter);
ToPack.append(dataPointer + i, ThisNaluSize); i += ThisNaluSize+4;
i += ThisNaluSize; }
if (PackData.BytesFree() < 184){
PackData.AddStuffing();
fillPacket(first, 0, 0, VideoCounter);
} }
ContCounter = &VideoCounter;
}else if (myMeta.tracks[currentPacket.getTrackId()].type == "audio"){ }else if (myMeta.tracks[currentPacket.getTrackId()].type == "audio"){
if (AppleCompat){ if (AppleCompat){
ToPack.append(TS::Packet::getPESAudioLeadIn(7+dataLen, lastVid)); bs = TS::Packet::getPESAudioLeadIn(7+dataLen, lastVid);
}else{ }else{
ToPack.append(TS::Packet::getPESAudioLeadIn(7+dataLen, currentPacket.getTime() * 90)); bs = TS::Packet::getPESAudioLeadIn(7+dataLen, currentPacket.getTime() * 90);
} }
ToPack.append(TS::GetAudioHeader(dataLen, myMeta.tracks[currentPacket.getTrackId()].init)); fillPacket(first, bs.data(), bs.size(), AudioCounter);
ToPack.append(dataPointer, dataLen); bs = TS::GetAudioHeader(dataLen, myMeta.tracks[currentPacket.getTrackId()].init);
fillPacket(first, bs.data(), bs.size(), AudioCounter);
ContCounter = &AudioCounter; ContCounter = &AudioCounter;
fillPacket(first, dataPointer,dataLen, AudioCounter);
if (PackData.BytesFree() < 184){
PackData.AddStuffing();
fillPacket(first, 0, 0, AudioCounter);
}
} }
bool first = true;
//send TS packets
while (ToPack.size()){
if (PacketNumber % 42 == 0){
HTTP_S.Chunkify(TS::PAT, 188, myConn);
HTTP_S.Chunkify(TS::PMT, 188, myConn);
PacketNumber += 2;
}
PackData.Clear();
/// \todo Update according to sendHeader()'s generated data.
//0x100 - 1 + currentPacket.getTrackId()
if (myMeta.tracks[currentPacket.getTrackId()].type == "video"){
PackData.PID(0x100);
}else{
PackData.PID(0x101);
}
PackData.ContinuityCounter((*ContCounter)++);
if (first){
PackData.UnitStart(1);
if (IsKeyFrame){
PackData.RandomAccess(1);
PackData.PCR(currentPacket.getTime() * 27000);
}
first = false;
}
unsigned int toSend = PackData.AddStuffing(ToPack.bytes(184));
std::string gonnaSend = ToPack.remove(toSend);
PackData.FillFree(gonnaSend);
HTTP_S.Chunkify(PackData.ToString(), 188, myConn);
PacketNumber ++;
}
} }
int OutHLS::canSeekms(unsigned int ms){ int OutHLS::canSeekms(unsigned int ms){

View file

@ -17,6 +17,7 @@ namespace Mist {
protected: protected:
HTTP::Parser HTTP_S; HTTP::Parser HTTP_S;
HTTP::Parser HTTP_R; HTTP::Parser HTTP_R;
void fillPacket(bool & first, const char * data, size_t dataLen, char & ContCounter);
std::string liveIndex(); std::string liveIndex();
std::string liveIndex(int tid); std::string liveIndex(int tid);
int canSeekms(unsigned int ms); int canSeekms(unsigned int ms);

View file

@ -7,11 +7,29 @@ namespace Mist {
haveAvcc = false; haveAvcc = false;
AudioCounter = 0; AudioCounter = 0;
VideoCounter = 0; VideoCounter = 0;
std::string tracks = config->getString("tracks");
streamName = config->getString("streamname"); streamName = config->getString("streamname");
parseData = true; parseData = true;
wantRequest = false; wantRequest = false;
initialize(); initialize();
std::string tracks = config->getString("tracks");
unsigned int currTrack = 0;
//loop over tracks, add any found track IDs to selectedTracks
if (tracks != ""){
selectedTracks.clear();
for (unsigned int i = 0; i < tracks.size(); ++i){
if (tracks[i] >= '0' && tracks[i] <= '9'){
currTrack = currTrack*10 + (tracks[i] - '0');
}else{
if (currTrack > 0){
selectedTracks.insert(currTrack);
}
currTrack = 0;
}
}
if (currTrack > 0){
selectedTracks.insert(currTrack);
}
}
} }
OutTS::~OutTS() {} OutTS::~OutTS() {}
@ -40,26 +58,58 @@ namespace Mist {
config = cfg; config = cfg;
} }
void OutTS::sendNext(){ void OutTS::fillPacket(bool & first, const char * data, size_t dataLen, char & ContCounter){
Socket::Buffer ToPack; if (!PackData.BytesFree()){
char * ContCounter = 0; myConn.SendNow(PackData.ToString(), 188);
bool IsKeyFrame = false; PackData.Clear();
}
if (!dataLen){return;}
if (PackData.BytesFree() == 184){
if (myMeta.tracks[currentPacket.getTrackId()].type == "video"){
PackData.PID(0x100);
}else{
PackData.PID(0x101);
}
PackData.ContinuityCounter(ContCounter++);
if (first){
PackData.UnitStart(1);
if (currentPacket.getInt("keyframe")){
PackData.RandomAccess(1);
PackData.PCR(currentPacket.getTime() * 27000);
}
first = false;
}
}
unsigned int tmp = PackData.FillFree(data, dataLen);
if (tmp != dataLen){
fillPacket(first, data+tmp, dataLen-tmp, ContCounter);
}
}
void OutTS::sendNext(){
char * dataPointer = 0; char * dataPointer = 0;
unsigned int dataLen = 0; unsigned int dataLen = 0;
currentPacket.getString("data", dataPointer, dataLen); currentPacket.getString("data", dataPointer, dataLen); //data
//detect packet type, and put converted data into ToPack. bool first = true;
std::string bs;
//prepare bufferstring
if (myMeta.tracks[currentPacket.getTrackId()].type == "video"){ if (myMeta.tracks[currentPacket.getTrackId()].type == "video"){
ToPack.append(TS::Packet::getPESVideoLeadIn(0ul, currentPacket.getTime() * 90)); bs = TS::Packet::getPESVideoLeadIn(0ul, currentPacket.getTime() * 90);
fillPacket(first, bs.data(), bs.size(),VideoCounter);
IsKeyFrame = currentPacket.getInt("keyframe"); if (currentPacket.getInt("keyframe")){
if (IsKeyFrame){
if (!haveAvcc){ if (!haveAvcc){
avccbox.setPayload(myMeta.tracks[currentPacket.getTrackId()].init); avccbox.setPayload(myMeta.tracks[currentPacket.getTrackId()].init);
haveAvcc = true; haveAvcc = true;
} }
ToPack.append(avccbox.asAnnexB()); bs = avccbox.asAnnexB();
fillPacket(first, bs.data(), bs.size(),VideoCounter);
} }
unsigned int i = 0; unsigned int i = 0;
while (i + 4 < (unsigned int)dataLen){ while (i + 4 < (unsigned int)dataLen){
@ -68,41 +118,21 @@ namespace Mist {
DEBUG_MSG(DLVL_WARN, "Too big NALU detected (%u > %d) - skipping!", ThisNaluSize + i + 4, dataLen); DEBUG_MSG(DLVL_WARN, "Too big NALU detected (%u > %d) - skipping!", ThisNaluSize + i + 4, dataLen);
break; break;
} }
ToPack.append("\000\000\000\001", 4); fillPacket(first, "\000\000\000\001",4,VideoCounter);
i += 4; fillPacket(first, dataPointer+i+4,ThisNaluSize,VideoCounter);
ToPack.append(dataPointer + i, ThisNaluSize); i += ThisNaluSize+4;
i += ThisNaluSize;
} }
ContCounter = &VideoCounter;
}else if (myMeta.tracks[currentPacket.getTrackId()].type == "audio"){ }else if (myMeta.tracks[currentPacket.getTrackId()].type == "audio"){
if (myMeta.tracks[currentPacket.getTrackId()].codec == "AAC"){ bs = TS::Packet::getPESAudioLeadIn(7+dataLen, currentPacket.getTime() * 90);
ToPack.append(TS::Packet::getPESAudioLeadIn(7+dataLen, currentPacket.getTime() * 90)); fillPacket(first, bs.data(), bs.size(),AudioCounter);
ToPack.append(TS::GetAudioHeader(dataLen, myMeta.tracks[currentPacket.getTrackId()].init)); bs = TS::GetAudioHeader(dataLen, myMeta.tracks[currentPacket.getTrackId()].init);
}else{ fillPacket(first, bs.data(), bs.size(),AudioCounter);
ToPack.append(TS::Packet::getPESAudioLeadIn(dataLen, currentPacket.getTime() * 90)); fillPacket(first, dataPointer,dataLen,AudioCounter);
}
ToPack.append(dataPointer, dataLen);
ContCounter = &AudioCounter;
} }
bool first = true; if (PackData.BytesFree() < 184){
//send TS packets PackData.AddStuffing();
while (ToPack.size()){ fillPacket(first, 0,0,VideoCounter);
PackData.Clear();
PackData.PID(0x100 - 1 + currentPacket.getTrackId());
PackData.ContinuityCounter((*ContCounter)++);
if (first){
PackData.UnitStart(1);
if (IsKeyFrame || myMeta.tracks[currentPacket.getTrackId()].type == "audio"){
PackData.RandomAccess(1);
PackData.PCR(currentPacket.getTime() * 27000);
}
first = false;
}
unsigned int toSend = PackData.AddStuffing(ToPack.bytes(184));
std::string gonnaSend = ToPack.remove(toSend);
PackData.FillFree(gonnaSend);
myConn.SendNow(PackData.ToString(), 188);
} }
} }
@ -154,12 +184,8 @@ namespace Mist {
} }
void OutTS::sendHeader(){ void OutTS::sendHeader(){
/// \todo if --tracks is set, clear selected tracks and fill with --tracks tracks.
myConn.SendNow(TS::PAT, 188); myConn.SendNow(TS::PAT, 188);
/// \todo Find a nice way to not use strings in this case myConn.SendNow(createPMT());
std::string pmt = createPMT();
myConn.SendNow(pmt.c_str(), 188);
//myConn.SendNow(TS::PMT, 188);
sentHeader = true; sentHeader = true;
} }

View file

@ -19,6 +19,7 @@ namespace Mist {
char AudioCounter; char AudioCounter;
MP4::AVCC avccbox; MP4::AVCC avccbox;
std::string createPMT(); std::string createPMT();
void fillPacket(bool & first, const char * data, size_t dataLen, char & ContCounter);
}; };
} }