#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(); }