From d2821a629e66c56e88399d1400ef16420c49d844 Mon Sep 17 00:00:00 2001 From: wouter spruit Date: Mon, 25 Aug 2014 19:23:15 +0200 Subject: [PATCH] Optimizes to TS outputs. --- src/output/output_hls.cpp | 130 ++++++++++++++++++++++---------------- src/output/output_hls.h | 3 +- src/output/output_ts.cpp | 122 +++++++++++++++++++++-------------- src/output/output_ts.h | 1 + 4 files changed, 154 insertions(+), 102 deletions(-) diff --git a/src/output/output_hls.cpp b/src/output/output_hls.cpp index b052ef5d..78a3f37e 100644 --- a/src/output/output_hls.cpp +++ b/src/output/output_hls.cpp @@ -112,16 +112,56 @@ namespace Mist { cfg->addBasicConnectorOptions(capa); config = cfg; } + //HIER - void OutHLS::sendNext(){ - Socket::Buffer ToPack; - char * ContCounter = 0; - bool IsKeyFrame = false; + + 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(){ + bool first = true; + char * ContCounter = 0; char * dataPointer = 0; unsigned int dataLen = 0; - currentPacket.getString("data", dataPointer, dataLen); - + currentPacket.getString("data", dataPointer, dataLen); //data + if (currentPacket.getTime() >= until){ DEBUG_MSG(DLVL_DEVEL, "(%d) Done sending fragment", getpid() ); stop(); @@ -130,19 +170,24 @@ namespace Mist { HTTP_S.Clean(); 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)); + 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); - IsKeyFrame = currentPacket.getInt("keyframe"); - if (IsKeyFrame){ + if (currentPacket.getInt("keyframe")){ if (!haveAvcc){ avccbox.setPayload(myMeta.tracks[currentPacket.getTrackId()].init); haveAvcc = true; } - ToPack.append(avccbox.asAnnexB()); + bs = avccbox.asAnnexB(); + fillPacket(first, bs.data(), bs.size(), VideoCounter); } + unsigned int i = 0; while (i + 4 < (unsigned int)dataLen){ 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); break; } - ToPack.append("\000\000\000\001", 4); - i += 4; - ToPack.append(dataPointer + i, ThisNaluSize); - i += ThisNaluSize; + fillPacket(first, "\000\000\000\001",4, VideoCounter); + fillPacket(first, dataPointer+i+4,ThisNaluSize, VideoCounter); + i += ThisNaluSize+4; } - ContCounter = &VideoCounter; - }else if (myMeta.tracks[currentPacket.getTrackId()].type == "audio"){ + if (PackData.BytesFree() < 184){ + PackData.AddStuffing(); + fillPacket(first, 0, 0, VideoCounter); + } + }else if (myMeta.tracks[currentPacket.getTrackId()].type == "audio"){ if (AppleCompat){ - ToPack.append(TS::Packet::getPESAudioLeadIn(7+dataLen, lastVid)); + bs = TS::Packet::getPESAudioLeadIn(7+dataLen, lastVid); }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)); - ToPack.append(dataPointer, dataLen); + fillPacket(first, bs.data(), bs.size(), AudioCounter); + bs = TS::GetAudioHeader(dataLen, myMeta.tracks[currentPacket.getTrackId()].init); + fillPacket(first, bs.data(), bs.size(), 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){ diff --git a/src/output/output_hls.h b/src/output/output_hls.h index 70031026..42358ad6 100644 --- a/src/output/output_hls.h +++ b/src/output/output_hls.h @@ -16,7 +16,8 @@ namespace Mist { void sendNext(); protected: 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(int tid); int canSeekms(unsigned int ms); diff --git a/src/output/output_ts.cpp b/src/output/output_ts.cpp index 589fc4f5..074c7213 100644 --- a/src/output/output_ts.cpp +++ b/src/output/output_ts.cpp @@ -7,11 +7,29 @@ namespace Mist { haveAvcc = false; AudioCounter = 0; VideoCounter = 0; - std::string tracks = config->getString("tracks"); streamName = config->getString("streamname"); parseData = true; wantRequest = false; 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() {} @@ -40,26 +58,58 @@ namespace Mist { config = cfg; } - void OutTS::sendNext(){ - Socket::Buffer ToPack; - char * ContCounter = 0; - bool IsKeyFrame = false; + void OutTS::fillPacket(bool & first, const char * data, size_t dataLen, char & ContCounter){ + if (!PackData.BytesFree()){ + myConn.SendNow(PackData.ToString(), 188); + 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; 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"){ - 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 (IsKeyFrame){ + if (currentPacket.getInt("keyframe")){ if (!haveAvcc){ avccbox.setPayload(myMeta.tracks[currentPacket.getTrackId()].init); haveAvcc = true; } - ToPack.append(avccbox.asAnnexB()); + bs = avccbox.asAnnexB(); + fillPacket(first, bs.data(), bs.size(),VideoCounter); } unsigned int i = 0; 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); break; } - ToPack.append("\000\000\000\001", 4); - i += 4; - ToPack.append(dataPointer + i, ThisNaluSize); - i += ThisNaluSize; + fillPacket(first, "\000\000\000\001",4,VideoCounter); + fillPacket(first, dataPointer+i+4,ThisNaluSize,VideoCounter); + i += ThisNaluSize+4; } - ContCounter = &VideoCounter; - }else if (myMeta.tracks[currentPacket.getTrackId()].type == "audio"){ - if (myMeta.tracks[currentPacket.getTrackId()].codec == "AAC"){ - ToPack.append(TS::Packet::getPESAudioLeadIn(7+dataLen, currentPacket.getTime() * 90)); - ToPack.append(TS::GetAudioHeader(dataLen, myMeta.tracks[currentPacket.getTrackId()].init)); - }else{ - ToPack.append(TS::Packet::getPESAudioLeadIn(dataLen, currentPacket.getTime() * 90)); - } - ToPack.append(dataPointer, dataLen); - ContCounter = &AudioCounter; + }else if (myMeta.tracks[currentPacket.getTrackId()].type == "audio"){ + bs = TS::Packet::getPESAudioLeadIn(7+dataLen, currentPacket.getTime() * 90); + fillPacket(first, bs.data(), bs.size(),AudioCounter); + bs = TS::GetAudioHeader(dataLen, myMeta.tracks[currentPacket.getTrackId()].init); + fillPacket(first, bs.data(), bs.size(),AudioCounter); + fillPacket(first, dataPointer,dataLen,AudioCounter); } - bool first = true; - //send TS packets - while (ToPack.size()){ - 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); + if (PackData.BytesFree() < 184){ + PackData.AddStuffing(); + fillPacket(first, 0,0,VideoCounter); } } @@ -154,12 +184,8 @@ namespace Mist { } void OutTS::sendHeader(){ - /// \todo if --tracks is set, clear selected tracks and fill with --tracks tracks. myConn.SendNow(TS::PAT, 188); - /// \todo Find a nice way to not use strings in this case - std::string pmt = createPMT(); - myConn.SendNow(pmt.c_str(), 188); - //myConn.SendNow(TS::PMT, 188); + myConn.SendNow(createPMT()); sentHeader = true; } diff --git a/src/output/output_ts.h b/src/output/output_ts.h index 9885a38e..6c63c845 100644 --- a/src/output/output_ts.h +++ b/src/output/output_ts.h @@ -19,6 +19,7 @@ namespace Mist { char AudioCounter; MP4::AVCC avccbox; std::string createPMT(); + void fillPacket(bool & first, const char * data, size_t dataLen, char & ContCounter); }; }