From 3baa8d15241365fc5f92dbef084ea3baf41beca9 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Sat, 29 Aug 2020 00:54:28 +0200 Subject: [PATCH] TS::Packet classes no longer rely on global PMT tracking --- lib/ts_packet.cpp | 17 ++++++----- lib/ts_packet.h | 8 ++++-- lib/ts_stream.cpp | 54 ++++++++++++++++++++++++----------- lib/ts_stream.h | 9 ++++-- src/analysers/analyser_ts.cpp | 11 ++++--- 5 files changed, 63 insertions(+), 36 deletions(-) diff --git a/lib/ts_packet.cpp b/lib/ts_packet.cpp index ebb3a0b8..94ed7ff0 100644 --- a/lib/ts_packet.cpp +++ b/lib/ts_packet.cpp @@ -27,9 +27,6 @@ "tortor commodo neque, vitae hendrerit nunc sem ut odio." #endif -std::set pmt_pids; -std::map stream_pids; - /// A standard Program Association Table, as generated by FFMPEG. /// Seems to be independent of the stream. // 0x47 = sync byte @@ -47,6 +44,8 @@ std::map stream_pids; // 0x2AB104B2 = CRC32 namespace TS{ + std::map stream_pids; + char PAT[188] ={ 0x47, 0x40, 0x00, 0x10, 0x00, 0x00, 0xB0, 0x0D, 0x00, 0x01, 0xC1, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x2A, 0xB1, 0x04, 0xB2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, @@ -276,7 +275,7 @@ namespace TS{ /// Prints a packet to stdout, for analyser purposes. /// If detail level contains bitmask 64, prints raw bytes after packet. - std::string Packet::toPrettyString(size_t indent, int detailLevel) const{ + std::string Packet::toPrettyString(const std::set &pidlist, size_t indent, int detailLevel) const{ if (!(*this)){return "[Invalid packet - no sync byte]";} std::stringstream output; output << std::string(indent, ' ') << "[PID " << getPID() << "|" << std::hex @@ -288,7 +287,7 @@ namespace TS{ case 17: output << "SDT"; break; case 0x1FFF: output << "Null"; break; default: - if (isPMT()){ + if (isPMT(pidlist)){ output << "PMT"; }else{ if (isStream()){ @@ -315,7 +314,7 @@ namespace TS{ return output.str(); } - if (pmt_pids.count(getPID())){ + if (pidlist.count(getPID())){ // PMT output << ((ProgramMappingTable *)this)->toPrettyString(indent + 2); return output.str(); @@ -349,7 +348,7 @@ namespace TS{ /// Returns true if this PID contains a PMT. /// Important caveat: only works if the corresponding PAT has been pretty-printed or had parsePIDs() called on it! - bool Packet::isPMT() const{return pmt_pids.count(getPID());} + bool Packet::isPMT(const std::set & pidList) const{return pidList.count(getPID());} /// Returns true if this PID contains a stream known from a PMT. /// Important caveat: only works if the corresponding PMT was pretty-printed or had parseStreams() called on it! @@ -834,8 +833,8 @@ namespace TS{ ((int)(strBuf[loc + 2]) << 8) | strBuf[loc + 3]; } - void ProgramAssociationTable::parsePIDs(){ - for (int i = 0; i < getProgramCount(); i++){pmt_pids.insert(getProgramPID(i));} + void ProgramAssociationTable::parsePIDs(std::set & pidlist){ + for (int i = 0; i < getProgramCount(); i++){pidlist.insert(getProgramPID(i));} } /// This function prints a program association table, diff --git a/lib/ts_packet.h b/lib/ts_packet.h index 3cc3a771..a74f4b38 100644 --- a/lib/ts_packet.h +++ b/lib/ts_packet.h @@ -17,6 +17,8 @@ /// Holds all TS processing related code. namespace TS{ + extern std::map stream_pids; + /// Class for reading and writing TS Streams. The class is capable of analyzing a packet of 188 /// bytes and calculating key values class Packet{ @@ -60,7 +62,7 @@ namespace TS{ // Helper functions operator bool() const; - bool isPMT() const; + bool isPMT(const std::set & pidList) const; bool isStream() const; void clear(); void setDefaultPAT(); @@ -82,7 +84,7 @@ namespace TS{ static std::string &getPESPS1LeadIn(unsigned int len, unsigned long long PTS, uint64_t bps = 0); // Printers and writers - std::string toPrettyString(size_t indent = 0, int detailLevel = 3) const; + std::string toPrettyString(const std::set & pidlist, size_t indent = 0, int detailLevel = 3) const; const char *getPayload() const; int getPayloadLength() const; const char *checkAndGetBuffer() const; @@ -107,7 +109,7 @@ namespace TS{ short getProgramNumber(short index) const; short getProgramPID(short index) const; int getCRC() const; - void parsePIDs(); + void parsePIDs(std::set & pidlist); std::string toPrettyString(size_t indent) const; }; diff --git a/lib/ts_stream.cpp b/lib/ts_stream.cpp index af37c63e..92af0093 100644 --- a/lib/ts_stream.cpp +++ b/lib/ts_stream.cpp @@ -15,7 +15,7 @@ tthread::recursive_mutex tMutex; namespace TS{ - bool Assembler::assemble(Stream & TSStrm, char * ptr, size_t len){ + bool Assembler::assemble(Stream & TSStrm, char * ptr, size_t len, bool parse){ bool ret = false; size_t offset = 0; size_t amount = 188-leftData.size(); @@ -26,9 +26,13 @@ namespace TS{ //Success! leftData.append(ptr, amount); tsBuf.FromPointer(leftData); - TSStrm.add(tsBuf); - ret = true; - if (!TSStrm.isDataTrack(tsBuf.getPID())){TSStrm.parse(tsBuf.getPID());} + if (!ret && tsBuf.getUnitStart()){ret = true;} + if (parse){ + TSStrm.parse(tsBuf, 0); + }else{ + TSStrm.add(tsBuf); + if (!TSStrm.isDataTrack(tsBuf.getPID())){TSStrm.parse(tsBuf.getPID());} + } offset = amount; leftData.assign(0,0); } @@ -45,9 +49,13 @@ namespace TS{ } if (offset + 188 <= len){ tsBuf.FromPointer(ptr + offset); - TSStrm.add(tsBuf); - if (!TSStrm.isDataTrack(tsBuf.getPID())){TSStrm.parse(tsBuf.getPID());} - ret = true; + if (!ret && tsBuf.getUnitStart()){ret = true;} + if (parse){ + TSStrm.parse(tsBuf, 0); + }else{ + TSStrm.add(tsBuf); + if (!TSStrm.isDataTrack(tsBuf.getPID())){TSStrm.parse(tsBuf.getPID());} + } }else{ leftData.assign(ptr + offset, len - offset); } @@ -182,7 +190,7 @@ namespace TS{ uint32_t tid = newPack.getPID(); bool unitStart = newPack.getUnitStart(); static uint32_t wantPrev = 0; - bool wantTrack = ((wantPrev == tid) || (tid == 0 || newPack.isPMT() || pidToCodec.count(tid))); + bool wantTrack = ((wantPrev == tid) || (tid == 0 || newPack.isPMT(pmtTracks) || pidToCodec.count(tid))); if (!wantTrack){return;} if (psCacheTid != tid || !psCache){ psCache = &(pesStreams[tid]); @@ -217,14 +225,9 @@ namespace TS{ // Handle PAT packets if (tid == 0){ ///\todo Keep track of updates in PAT instead of keeping only the last PAT as a reference - associationTable = psCache->back(); - associationTable.parsePIDs(); lastPAT = Util::bootSecs(); - - size_t pmtCount = associationTable.getProgramCount(); - for (size_t i = 0; i < pmtCount; i++){pmtTracks.insert(associationTable.getProgramPID(i));} - + associationTable.parsePIDs(pmtTracks); pesStreams.erase(0); psCacheTid = 0; psCache = 0; @@ -285,7 +288,8 @@ namespace TS{ void Stream::parse(Packet &newPack, uint64_t bytePos){ add(newPack, bytePos); - if (newPack.getUnitStart()){parse(newPack.getPID());} + unsigned int pid = newPack.getPID(); + if (!pid || newPack.getUnitStart()){parse(pid);} } bool Stream::hasPacketOnEachTrack() const{ @@ -335,7 +339,9 @@ namespace TS{ } for (std::map::const_iterator i = seenUnitStart.begin(); i != seenUnitStart.end(); i++){ - if (pidToCodec.count(i->first) && i->second > 1){return true;} + if (pidToCodec.count(i->first) && i->second > 1){ + return true; + } } return false; @@ -907,7 +913,21 @@ namespace TS{ } } - if (packTrack){getPacket(packTrack, pack);} + if (packTrack){ + getPacket(packTrack, pack); + return; + } + + //Nothing yet...? Let's see if we can parse something. + for (std::map::const_iterator i = seenUnitStart.begin(); i != seenUnitStart.end(); i++){ + if (pidToCodec.count(i->first) && i->second > 1){ + parse(i->first); + if (hasPacket(i->first)){ + getPacket(packTrack, pack); + return; + } + } + } } void Stream::initializeMetadata(DTSC::Meta &meta, size_t tid, size_t mappingId){ diff --git a/lib/ts_stream.h b/lib/ts_stream.h index 6ffaf024..0cc1da7e 100644 --- a/lib/ts_stream.h +++ b/lib/ts_stream.h @@ -45,7 +45,10 @@ namespace TS{ void clear(); }; + class Assembler; + class Stream{ + friend class Assembler; public: Stream(); ~Stream(); @@ -78,6 +81,8 @@ namespace TS{ ProgramAssociationTable associationTable; std::map remainders; + std::set pmtTracks; + std::map lastPMT; std::map mappingTable; @@ -102,14 +107,12 @@ namespace TS{ std::map rolloverCount; std::map lastms; - std::set pmtTracks; - void parsePES(size_t tid, bool finished = false); }; class Assembler{ public: - bool assemble(Stream & TSStrm, char * ptr, size_t len); + bool assemble(Stream & TSStrm, char * ptr, size_t len, bool parse = false); private: Util::ResizeablePointer leftData; TS::Packet tsBuf; diff --git a/src/analysers/analyser_ts.cpp b/src/analysers/analyser_ts.cpp index 34bb240c..a0ed3c1e 100644 --- a/src/analysers/analyser_ts.cpp +++ b/src/analysers/analyser_ts.cpp @@ -17,6 +17,9 @@ #include #include + +std::set pmtTracks; + void AnalyserTS::init(Util::Config &conf){ Analyser::init(conf); JSON::Value opt; @@ -68,13 +71,13 @@ bool AnalyserTS::parsePacket(){ } payloads.erase(packet.getPID()); } - if (packet.getPID() == 0){((TS::ProgramAssociationTable *)&packet)->parsePIDs();} - if (packet.isPMT()){((TS::ProgramMappingTable *)&packet)->parseStreams();} + if (packet.getPID() == 0){((TS::ProgramAssociationTable *)&packet)->parsePIDs(pmtTracks);} + if (packet.isPMT(pmtTracks)){((TS::ProgramMappingTable *)&packet)->parseStreams();} if ((((detail & 2) && !packet.isStream()) || ((detail & 4) && packet.isStream())) && (!pidOnly || packet.getPID() == pidOnly)){ - std::cout << packet.toPrettyString(0, detail); + std::cout << packet.toPrettyString(pmtTracks, 0, detail); } - if (packet.getPID() >= 0x10 && !packet.isPMT() && packet.getPID() != 17 && + if (packet.getPID() >= 0x10 && !packet.isPMT(pmtTracks) && packet.getPID() != 17 && (payloads[packet.getPID()].size() || packet.getUnitStart())){ payloads[packet.getPID()].append(packet.getPayload(), packet.getPayloadLength()); }