TS::Packet classes no longer rely on global PMT tracking
This commit is contained in:
parent
7423868de4
commit
3baa8d1524
5 changed files with 63 additions and 36 deletions
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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<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){
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue