TS::Packet classes no longer rely on global PMT tracking

This commit is contained in:
Thulinma 2020-08-29 00:54:28 +02:00
parent 7423868de4
commit 3baa8d1524
5 changed files with 63 additions and 36 deletions

View file

@ -27,9 +27,6 @@
"tortor commodo neque, vitae hendrerit nunc sem ut odio."
#endif
std::set<unsigned int> pmt_pids;
std::map<unsigned int, std::string> 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<unsigned int, std::string> stream_pids;
// 0x2AB104B2 = CRC32
namespace TS{
std::map<unsigned int, std::string> 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<unsigned int> &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<unsigned int> & 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<unsigned int> & pidlist){
for (int i = 0; i < getProgramCount(); i++){pidlist.insert(getProgramPID(i));}
}
/// This function prints a program association table,

View file

@ -17,6 +17,8 @@
/// Holds all TS processing related code.
namespace TS{
extern std::map<unsigned int, std::string> 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<unsigned int> & 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<unsigned int> & 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<unsigned int> & pidlist);
std::string toPrettyString(size_t indent) const;
};

View file

@ -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);
if (!ret && tsBuf.getUnitStart()){ret = true;}
if (parse){
TSStrm.parse(tsBuf, 0);
}else{
TSStrm.add(tsBuf);
ret = true;
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);
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());}
ret = true;
}
}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<size_t, uint32_t>::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<size_t, uint32_t>::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){

View file

@ -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<size_t, ADTSRemainder> remainders;
std::set<unsigned int> pmtTracks;
std::map<size_t, uint64_t> lastPMT;
std::map<size_t, ProgramMappingTable> mappingTable;
@ -102,14 +107,12 @@ namespace TS{
std::map<size_t, size_t> rolloverCount;
std::map<size_t, unsigned long long> lastms;
std::set<size_t> 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;

View file

@ -17,6 +17,9 @@
#include <string>
#include <unistd.h>
std::set<unsigned int> 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());
}