Optimizes to TS outputs.
This commit is contained in:
parent
286d6cba5c
commit
d2821a629e
4 changed files with 154 additions and 102 deletions
|
@ -112,16 +112,56 @@ namespace Mist {
|
||||||
cfg->addBasicConnectorOptions(capa);
|
cfg->addBasicConnectorOptions(capa);
|
||||||
config = cfg;
|
config = cfg;
|
||||||
}
|
}
|
||||||
|
//HIER
|
||||||
|
|
||||||
void OutHLS::sendNext(){
|
|
||||||
Socket::Buffer ToPack;
|
void OutHLS::fillPacket(bool & first, const char * data, size_t dataLen, char & ContCounter){
|
||||||
char * ContCounter = 0;
|
|
||||||
bool IsKeyFrame = false;
|
|
||||||
|
|
||||||
|
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;
|
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() );
|
||||||
stop();
|
stop();
|
||||||
|
@ -130,19 +170,24 @@ namespace Mist {
|
||||||
HTTP_S.Clean();
|
HTTP_S.Clean();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//detect packet type, and put converted data into ToPack.
|
std::string bs;
|
||||||
if (myMeta.tracks[currentPacket.getTrackId()].type == "video"){
|
//prepare bufferstring
|
||||||
ToPack.append(TS::Packet::getPESVideoLeadIn(0ul, currentPacket.getTime() * 90));
|
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 (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){
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
ContCounter = &VideoCounter;
|
if (PackData.BytesFree() < 184){
|
||||||
}else if (myMeta.tracks[currentPacket.getTrackId()].type == "audio"){
|
PackData.AddStuffing();
|
||||||
|
fillPacket(first, 0, 0, VideoCounter);
|
||||||
|
}
|
||||||
|
}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){
|
||||||
|
|
|
@ -16,7 +16,8 @@ namespace Mist {
|
||||||
void sendNext();
|
void sendNext();
|
||||||
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);
|
||||||
|
|
|
@ -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"){
|
bs = TS::Packet::getPESAudioLeadIn(7+dataLen, currentPacket.getTime() * 90);
|
||||||
if (myMeta.tracks[currentPacket.getTrackId()].codec == "AAC"){
|
fillPacket(first, bs.data(), bs.size(),AudioCounter);
|
||||||
ToPack.append(TS::Packet::getPESAudioLeadIn(7+dataLen, currentPacket.getTime() * 90));
|
bs = TS::GetAudioHeader(dataLen, myMeta.tracks[currentPacket.getTrackId()].init);
|
||||||
ToPack.append(TS::GetAudioHeader(dataLen, myMeta.tracks[currentPacket.getTrackId()].init));
|
fillPacket(first, bs.data(), bs.size(),AudioCounter);
|
||||||
}else{
|
fillPacket(first, dataPointer,dataLen,AudioCounter);
|
||||||
ToPack.append(TS::Packet::getPESAudioLeadIn(dataLen, currentPacket.getTime() * 90));
|
|
||||||
}
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue