136 lines
4.5 KiB
C++
136 lines
4.5 KiB
C++
#include <iostream>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <cstdlib>
|
|
#include <cstdio>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <mist/ts_packet.h> //TS support
|
|
#include <mist/dtsc.h> //DTSC support
|
|
#include <mist/mp4.h> //For initdata conversion
|
|
#include <mist/config.h>
|
|
|
|
///\brief Holds everything unique to converters.
|
|
namespace Converters {
|
|
///\brief Converts DTSC from stdin to TS on stdout.
|
|
///\return The return code for the converter.
|
|
int DTSC2TS(){
|
|
char charBuffer[1024 * 10];
|
|
unsigned int charCount;
|
|
std::string StrData;
|
|
TS::Packet PackData;
|
|
DTSC::Stream Strm;
|
|
int PacketNumber = 0;
|
|
long long unsigned int TimeStamp = 0;
|
|
int ThisNaluSize;
|
|
char VideoCounter = 0;
|
|
char AudioCounter = 0;
|
|
bool WritePesHeader;
|
|
bool IsKeyFrame;
|
|
MP4::AVCC avccbox;
|
|
bool haveAvcc = false;
|
|
std::stringstream TSBuf;
|
|
|
|
|
|
while (std::cin.good()){
|
|
if (Strm.parsePacket(StrData)){
|
|
if (Strm.lastType() == DTSC::PAUSEMARK){
|
|
TSBuf.flush();
|
|
if (TSBuf.str().size()){
|
|
std::cout << TSBuf.str();
|
|
TSBuf.str("");
|
|
PacketNumber = 0;
|
|
}
|
|
TSBuf.str("");
|
|
}
|
|
if ( !haveAvcc){
|
|
avccbox.setPayload(Strm.metadata["video"]["init"].asString());
|
|
haveAvcc = true;
|
|
}
|
|
if (Strm.lastType() == DTSC::VIDEO || Strm.lastType() == DTSC::AUDIO){
|
|
Socket::Buffer ToPack;
|
|
//write PAT and PMT TS packets
|
|
if (PacketNumber == 0){
|
|
PackData.DefaultPAT();
|
|
TSBuf.write(PackData.ToString(), 188);
|
|
PackData.DefaultPMT();
|
|
TSBuf.write(PackData.ToString(), 188);
|
|
PacketNumber += 2;
|
|
}
|
|
|
|
int PIDno = 0;
|
|
char * ContCounter = 0;
|
|
if (Strm.lastType() == DTSC::VIDEO){
|
|
IsKeyFrame = Strm.getPacket().isMember("keyframe");
|
|
if (IsKeyFrame){
|
|
TimeStamp = (Strm.getPacket()["time"].asInt() * 27000);
|
|
}
|
|
ToPack.append(avccbox.asAnnexB());
|
|
while (Strm.lastData().size()){
|
|
ThisNaluSize = (Strm.lastData()[0] << 24) + (Strm.lastData()[1] << 16) + (Strm.lastData()[2] << 8) + Strm.lastData()[3];
|
|
Strm.lastData().replace(0, 4, TS::NalHeader, 4);
|
|
if (ThisNaluSize + 4 == Strm.lastData().size()){
|
|
ToPack.append(Strm.lastData());
|
|
break;
|
|
}else{
|
|
ToPack.append(Strm.lastData().c_str(), ThisNaluSize + 4);
|
|
Strm.lastData().erase(0, ThisNaluSize + 4);
|
|
}
|
|
}
|
|
ToPack.prepend(TS::Packet::getPESVideoLeadIn(0ul, Strm.getPacket()["time"].asInt() * 90));
|
|
PIDno = 0x100;
|
|
ContCounter = &VideoCounter;
|
|
}else if (Strm.lastType() == DTSC::AUDIO){
|
|
ToPack.append(TS::GetAudioHeader(Strm.lastData().size(), Strm.metadata["audio"]["init"].asString()));
|
|
ToPack.append(Strm.lastData());
|
|
ToPack.prepend(TS::Packet::getPESAudioLeadIn(ToPack.bytes(1073741824ul), Strm.getPacket()["time"].asInt() * 90));
|
|
PIDno = 0x101;
|
|
ContCounter = &AudioCounter;
|
|
}
|
|
|
|
//initial packet
|
|
PackData.Clear();
|
|
PackData.PID(PIDno);
|
|
PackData.ContinuityCounter(( *ContCounter)++);
|
|
PackData.UnitStart(1);
|
|
if (IsKeyFrame){
|
|
PackData.RandomAccess(1);
|
|
PackData.PCR(TimeStamp);
|
|
}
|
|
unsigned int toSend = PackData.AddStuffing(ToPack.bytes(184));
|
|
std::string gonnaSend = ToPack.remove(toSend);
|
|
PackData.FillFree(gonnaSend);
|
|
TSBuf.write(PackData.ToString(), 188);
|
|
PacketNumber++;
|
|
|
|
//rest of packets
|
|
while (ToPack.size()){
|
|
PackData.Clear();
|
|
PackData.PID(PIDno);
|
|
PackData.ContinuityCounter(( *ContCounter)++);
|
|
toSend = PackData.AddStuffing(ToPack.bytes(184));
|
|
gonnaSend = ToPack.remove(toSend);
|
|
PackData.FillFree(gonnaSend);
|
|
TSBuf.write(PackData.ToString(), 188);
|
|
PacketNumber++;
|
|
}
|
|
|
|
}
|
|
}else{
|
|
std::cin.read(charBuffer, 1024 * 10);
|
|
charCount = std::cin.gcount();
|
|
StrData.append(charBuffer, charCount);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
///\brief Entry point for DTSC2TS, simply calls Converters::DTSC2TS().
|
|
int main(int argc, char* argv[]){
|
|
Util::Config conf = Util::Config(argv[0], PACKAGE_VERSION);
|
|
conf.parseArgs(argc, argv);
|
|
return Converters::DTSC2TS();
|
|
}
|