TS library unification, simplicifation, prettification.

This commit is contained in:
Thulinma 2015-02-19 02:54:47 +01:00
parent d93fb0c4dc
commit 1393033d14
2 changed files with 254 additions and 113 deletions

View file

@ -4,6 +4,8 @@
#include <sstream> #include <sstream>
#include <iomanip> #include <iomanip>
#include <string.h> #include <string.h>
#include <set>
#include <map>
#include "ts_packet.h" #include "ts_packet.h"
#include "defines.h" #include "defines.h"
@ -11,6 +13,10 @@
#define FILLER_DATA "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent commodo vulputate urna eu commodo. Cras tempor velit nec nulla placerat volutpat. Proin eleifend blandit quam sit amet suscipit. Pellentesque vitae tristique lorem. Maecenas facilisis consequat neque, vitae iaculis eros vulputate ut. Suspendisse ut arcu non eros vestibulum pulvinar id sed erat. Nam dictum tellus vel tellus rhoncus ut mollis tellus fermentum. Fusce volutpat consectetur ante, in mollis nisi euismod vulputate. Curabitur vitae facilisis ligula. Sed sed gravida dolor. Integer eu eros a dolor lobortis ullamcorper. Mauris interdum elit non neque interdum dictum. Suspendisse imperdiet eros sed sapien cursus pulvinar. Vestibulum ut dolor lectus, id commodo elit. Cras convallis varius leo eu porta. Duis luctus sapien nec dui adipiscing quis interdum nunc congue. Morbi pharetra aliquet mauris vitae tristique. Etiam feugiat sapien quis augue elementum id ultricies magna vulputate. Phasellus luctus, leo id egestas consequat, eros tortor commodo neque, vitae hendrerit nunc sem ut odio." #define FILLER_DATA "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent commodo vulputate urna eu commodo. Cras tempor velit nec nulla placerat volutpat. Proin eleifend blandit quam sit amet suscipit. Pellentesque vitae tristique lorem. Maecenas facilisis consequat neque, vitae iaculis eros vulputate ut. Suspendisse ut arcu non eros vestibulum pulvinar id sed erat. Nam dictum tellus vel tellus rhoncus ut mollis tellus fermentum. Fusce volutpat consectetur ante, in mollis nisi euismod vulputate. Curabitur vitae facilisis ligula. Sed sed gravida dolor. Integer eu eros a dolor lobortis ullamcorper. Mauris interdum elit non neque interdum dictum. Suspendisse imperdiet eros sed sapien cursus pulvinar. Vestibulum ut dolor lectus, id commodo elit. Cras convallis varius leo eu porta. Duis luctus sapien nec dui adipiscing quis interdum nunc congue. Morbi pharetra aliquet mauris vitae tristique. Etiam feugiat sapien quis augue elementum id ultricies magna vulputate. Phasellus luctus, leo id egestas consequat, eros tortor commodo neque, vitae hendrerit nunc sem ut odio."
#endif #endif
std::set<unsigned int> pmt_pids;
std::map<unsigned int, std::string> stream_pids;
namespace TS { namespace TS {
/// This constructor creates an empty Packet, ready for use for either reading or writing. /// This constructor creates an empty Packet, ready for use for either reading or writing.
/// All this constructor does is call Packet::Clear(). /// All this constructor does is call Packet::Clear().
@ -39,9 +45,14 @@ namespace TS {
/// \return true if it was possible to read in a full packet, false otherwise. /// \return true if it was possible to read in a full packet, false otherwise.
bool Packet::FromFile(FILE * data) { bool Packet::FromFile(FILE * data) {
strBuf.resize(188); strBuf.resize(188);
long long int pos = ftell(data);
if (!fread((void *)strBuf.data(), 188, 1, data)) { if (!fread((void *)strBuf.data(), 188, 1, data)) {
return false; return false;
} }
if (strBuf[0] != 0x47){
INFO_MSG("Failed to read a good packet on pos %lld", pos);
return false;
}
return true; return true;
} }
@ -76,16 +87,16 @@ namespace TS {
/// Sets the Continuity Counter of a single Packet. /// Sets the Continuity Counter of a single Packet.
/// \param NewContinuity The new Continuity Counter of the packet. /// \param NewContinuity The new Continuity Counter of the packet.
void Packet::ContinuityCounter(int NewContinuity) { void Packet::continuityCounter(int NewContinuity) {
if (strBuf.size() < 4) { if (strBuf.size() < 4) {
strBuf.resize(4); strBuf.resize(4);
} }
strBuf[3] = (strBuf[3] & 0xF0) + (NewContinuity & 0x0F); strBuf[3] = (strBuf[3] & 0xF0) | (NewContinuity & 0x0F);
} }
/// Gets the Continuity Counter of a single Packet. /// Gets the Continuity Counter of a single Packet.
/// \return The value of the Continuity Counter. /// \return The value of the Continuity Counter.
int Packet::ContinuityCounter() { int Packet::continuityCounter() {
return (strBuf[3] & 0x0F); return (strBuf[3] & 0x0F);
} }
@ -154,10 +165,9 @@ namespace TS {
if (!(strBuf[5] & 0x10)) { if (!(strBuf[5] & 0x10)) {
return -1; return -1;
} }
int64_t Result = 0; int64_t Result = (((strBuf[6] << 24) | (strBuf[7] << 16) | (strBuf[8] << 8) | strBuf[9]) << 1) | (strBuf[10] >> 7);
Result = (((strBuf[6] << 24) + (strBuf[7] << 16) + (strBuf[8] << 8) + strBuf[9]) << 1) + (strBuf[10] & 0x80 >> 7); Result *= 300;
Result = Result * 300; Result |= (((strBuf[10] & 0x01) << 8) + strBuf[11]);
Result += (((strBuf[10] & 0x01) << 8) + strBuf[11]);
return Result; return Result;
} }
@ -176,28 +186,23 @@ namespace TS {
Result += (((strBuf[10 + 6] & 0x01) << 8) + strBuf[11 + 6]); Result += (((strBuf[10 + 6] & 0x01) << 8) + strBuf[11 + 6]);
return Result; return Result;
} }
/// Gets the sync byte of a Packet.
/// \return The packet's sync byte
unsigned int Packet::getSyncByte() {
return (unsigned int)strBuf[0];
}
/// Gets the transport error inficator of a Packet /// Gets the transport error inficator of a Packet
/// \return The transport error inficator of a Packet /// \return The transport error inficator of a Packet
unsigned int Packet::getTransportErrorIndicator() { bool Packet::transportError() {
return (unsigned int)((strBuf[1] >> 7) & (0x01)); return strBuf[1] & 0x80;
} }
/// Gets the payload unit start inficator of a Packet /// Gets the payload unit start inficator of a Packet
/// \return The payload unit start inficator of a Packet /// \return The payload unit start inficator of a Packet
unsigned int Packet::getPayloadUnitStartIndicator() { bool Packet::unitStart() {
return (unsigned int)((strBuf[1] >> 6) & (0x01)); return strBuf[1] & 0x40;
} }
/// Gets the transport priority of a Packet /// Gets the transport priority of a Packet
/// \return The transport priority of a Packet /// \return The transport priority of a Packet
unsigned int Packet::getTransportPriority() { bool Packet::priority() {
return (unsigned int)((strBuf[1] >> 5) & (0x01)); return strBuf[1] & 0x20;
} }
/// Gets the transport scrambling control of a Packet /// Gets the transport scrambling control of a Packet
@ -215,55 +220,105 @@ namespace TS {
return (int)strBuf[4]; return (int)strBuf[4];
} }
Packet::operator bool(){
return strBuf.size() && strBuf[0] == 0x47;
}
/// Prints a packet to stdout, for analyser purposes. /// Prints a packet to stdout, for analyser purposes.
std::string Packet::toPrettyString(size_t indent) { std::string Packet::toPrettyString(size_t indent, int detailLevel) {
if (!(*this)){
return "[Invalid packet - no sync byte]";
}
std::stringstream output; std::stringstream output;
output << std::string(indent, ' ') << "TS Packet: " << (strBuf[0] == 0x47) << std::endl; output << std::string(indent, ' ') << "[PID " << PID() << "|" << std::hex << continuityCounter() << std::dec << ": " << dataSize() << "b ";
output << std::string(indent + 2, ' ') << "Transport Error Indicator: " << getTransportErrorIndicator() << std::endl; if (!PID()){
output << std::string(indent + 2, ' ') << "Payload Unit Start Indicator: " << getPayloadUnitStartIndicator() << std::endl; output << "PAT";
output << std::string(indent + 2, ' ') << "Transport Priority: " << getTransportPriority() << std::endl; }else{
output << std::string(indent + 2, ' ') << "PID: " << PID() << std::endl; if (pmt_pids.count(PID())){
output << std::string(indent + 2, ' ') << "Transport Scrambling Control: " << getTransportScramblingControl() << std::endl; output << "PMT";
output << std::string(indent + 2, ' ') << "Adaptation Field: " << AdaptationField() << std::endl; }else{
output << std::string(indent + 2, ' ') << "Continuity Counter: " << ContinuityCounter() << std::endl; if (stream_pids.count(PID())){
if (AdaptationField() > 1) { output << stream_pids[PID()];
output << std::string(indent + 4, ' ') << "Adaptation Length: " << AdaptationFieldLen() << std::endl; }else{
if (AdaptationFieldLen()) { output << "Unknown";
output << std::string(indent + 4, ' ') << "Discontinuity Indicator: " << DiscontinuityIndicator() << std::endl;
output << std::string(indent + 4, ' ') << "Random Access: " << RandomAccess() << std::endl;
output << std::string(indent + 4, ' ') << "Elementary Stream Priority Indicator: " << elementaryStreamPriorityIndicator() << std::endl;
output << std::string(indent + 4, ' ') << "PCRFlag: " << PCRFlag() << std::endl;
output << std::string(indent + 4, ' ') << "OPCRFlag: " << OPCRFlag() << std::endl;
output << std::string(indent + 4, ' ') << "Splicing Point Flag: " << splicingPointFlag() << std::endl;
///\todo Implement this
//output << std::string(indent + 4, ' ') << "Transport Private Data Flag: " << transportPrivateDataFlag() << std::endl;
//output << std::string(indent + 4, ' ') << "Adaptation Field Extension Flag: " << adaptationFieldExtensionFlag() << std::endl;
if (PCRFlag()) {
output << std::string(indent + 6, ' ') << "PCR: " << PCR() << "( " << (double)PCR() / 27000000 << " s )" << std::endl;
}
if (OPCRFlag()) {
output << std::string(indent + 6, ' ') << "OPCR: " << PCR() << "( " << (double)OPCR() / 27000000 << " s )" << std::endl;
} }
} }
} }
if (PID() == 0x00) { output << "]";
//program association table if (unitStart()){
output << ((ProgramAssociationTable *)this)->toPrettyString(indent + 2); output << " [Start]";
} else {
output << std::string(indent + 2, ' ') << "Data: " << 184 - ((AdaptationField() > 1) ? AdaptationFieldLen() + 1 : 0) << " bytes" << std::endl;
} }
if (AdaptationField() > 1 && AdaptationFieldLen()) {
if (discontinuity()){
output << " [Discontinuity]";
}
if (randomAccess()){
output << " [RandomXS]";
}
if (hasPCR()) {
output << " [PCR " << (double)PCR() / 27000000 << "s]";
}
if (hasOPCR()) {
output<< " [OPCR: " << (double)OPCR() / 27000000 << "s]";
}
}
output << std::endl;
if (!PID()) {
//PAT
if (detailLevel >= 2){
output << ((ProgramAssociationTable *)this)->toPrettyString(indent + 2);
}else{
((ProgramAssociationTable *)this)->toPrettyString(indent + 2);
}
return output.str();
}
if (pmt_pids.count(PID())){
//PMT
if (detailLevel >= 2){
output << ((ProgramMappingTable *)this)->toPrettyString(indent + 2);
}else{
((ProgramMappingTable *)this)->toPrettyString(indent + 2);
}
return output.str();
}
if (detailLevel >= 3){
output << std::string(indent+2, ' ') << "Raw data bytes:";
unsigned int size = dataSize();
char * dPointer = dataPointer();
for (unsigned int i = 0; i < size; ++i){
if (!(i % 32)){
output << std::endl << std::string(indent + 4, ' ');
}
output << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)dPointer[i] << " ";
if ((i % 4) == 3){
output << " ";
}
}
output << std::endl;
}
return output.str(); return output.str();
} }
/// Gets whether a new unit starts in this Packet. char * Packet::dataPointer(){
/// \return The start of a new unit. return (char*)strBuf.data() + 188 - dataSize();
int Packet::UnitStart() { }
return (strBuf[1] & 0x40) >> 6;
unsigned int Packet::dataSize(){
return 184 - ((AdaptationField() > 1) ? AdaptationFieldLen() + 1 : 0);
}
/// Returns true if this PID contains a PMT.
/// Important caveat: only works if the corresponding PAT has been pretty-printed earlier!
bool Packet::isPMT(){
return pmt_pids.count(PID());
} }
/// Sets the start of a new unit in this Packet. /// Sets the start of a new unit in this Packet.
/// \param NewVal The new value for the start of a unit. /// \param NewVal The new value for the start of a unit.
void Packet::UnitStart(int NewVal) { void Packet::unitStart(bool NewVal) {
if (NewVal) { if (NewVal) {
strBuf[1] |= 0x40; strBuf[1] |= 0x40;
} else { } else {
@ -273,46 +328,44 @@ namespace TS {
/// Gets the elementary stream priority indicator of a Packet /// Gets the elementary stream priority indicator of a Packet
/// \return The elementary stream priority indicator of a Packet /// \return The elementary stream priority indicator of a Packet
int Packet::elementaryStreamPriorityIndicator() { bool Packet::ESpriority() {
return (strBuf[5] >> 5) & 0x01; return strBuf[5] & 0x20;
} }
bool Packet::discontinuity() {
return strBuf[5] & 0x80;
}
/// Gets whether this Packet can be accessed at random (indicates keyframe). /// Gets whether this Packet can be accessed at random (indicates keyframe).
/// \return Whether or not this Packet contains a keyframe. /// \return Whether or not this Packet contains a keyframe.
int Packet::DiscontinuityIndicator() { bool Packet::randomAccess() {
return (strBuf[5] >> 7) & 0x01;
}
int Packet::RandomAccess() {
if (AdaptationField() < 2) { if (AdaptationField() < 2) {
return -1; return false;
} }
return (strBuf[5] & 0x40) >> 6; return strBuf[5] & 0x40;
} }
///Gets the value of the PCR flag ///Gets the value of the PCR flag
///\return true if there is a PCR, false otherwise ///\return true if there is a PCR, false otherwise
int Packet::PCRFlag() { bool Packet::hasPCR() {
return (strBuf[5] >> 4) & 0x01; return strBuf[5] & 0x10;
} }
///Gets the value of the OPCR flag ///Gets the value of the OPCR flag
///\return true if there is an OPCR, false otherwise ///\return true if there is an OPCR, false otherwise
int Packet::OPCRFlag() { bool Packet::hasOPCR() {
return (strBuf[5] >> 3) & 0x01; return strBuf[5] & 0x08;
} }
///Gets the value of the splicing point flag ///Gets the value of the splicing point flag
///\return the value of the splicing point flag ///\return the value of the splicing point flag
int Packet::splicingPointFlag() { bool Packet::splicingPoint() {
return (strBuf[5] >> 2) & 0x01; return strBuf[5] & 0x04;
} }
///Gets the value of the transport private data point flag ///Gets the value of the transport private data point flag
///\return the value of the transport private data point flag ///\return the value of the transport private data point flag
void Packet::RandomAccess(int NewVal) { void Packet::randomAccess(bool NewVal) {
if (AdaptationField() == 3) { if (AdaptationField() == 3) {
if (strBuf.size() < 6) { if (strBuf.size() < 6) {
strBuf.resize(6); strBuf.resize(6);
@ -343,7 +396,7 @@ namespace TS {
void Packet::DefaultPAT() { void Packet::DefaultPAT() {
static int MyCntr = 0; static int MyCntr = 0;
strBuf = std::string(PAT, 188); strBuf = std::string(PAT, 188);
ContinuityCounter(MyCntr++); continuityCounter(MyCntr++);
MyCntr %= 0x10; MyCntr %= 0x10;
} }
@ -351,7 +404,7 @@ namespace TS {
void Packet::DefaultPMT() { void Packet::DefaultPMT() {
static int MyCntr = 0; static int MyCntr = 0;
strBuf = std::string(PMT, 188); strBuf = std::string(PMT, 188);
ContinuityCounter(MyCntr++); continuityCounter(MyCntr++);
MyCntr %= 0x10; MyCntr %= 0x10;
} }
@ -681,6 +734,7 @@ namespace TS {
output << std::string(indent + 4, ' ') << "[" << i + 1 << "] "; output << std::string(indent + 4, ' ') << "[" << i + 1 << "] ";
output << "Program Number: " << getProgramNumber(i) << ", "; output << "Program Number: " << getProgramNumber(i) << ", ";
output << (getProgramNumber(i) == 0 ? "Network" : "Program Map") << " PID: " << getProgramPID(i); output << (getProgramNumber(i) == 0 ? "Network" : "Program Map") << " PID: " << getProgramPID(i);
pmt_pids.insert(getProgramPID(i));
output << std::endl; output << std::endl;
} }
output << std::string(indent + 2, ' ') << "CRC32: " << std::hex << std::setw(8) << std::setfill('0') << std::uppercase << getCRC() << std::dec << std::endl; output << std::string(indent + 2, ' ') << "CRC32: " << std::hex << std::setw(8) << std::setfill('0') << std::uppercase << getCRC() << std::dec << std::endl;
@ -688,6 +742,80 @@ namespace TS {
} }
ProgramMappingEntry::ProgramMappingEntry(char * begin, char * end){
data = begin;
boundary = end;
}
ProgramMappingEntry::operator bool() const {
return data && (data < boundary);
}
int ProgramMappingEntry::streamType(){
return data[0];
}
std::string ProgramMappingEntry::codec(){
switch (streamType()){
case 0x01:
case 0x03: return "MPEG1";
case 0x02: return "MPEG1/2";
case 0x04:
case 0x05:
case 0x06: return "MPEG2";
case 0x07: return "MHEG";
case 0x08: return "MPEG2 DSM CC";
case 0x09: return "H.222.1";
case 0x0A: return "DSM CC encapsulation";
case 0x0B: return "DSM CC U-N";
case 0x0C: return "DSM CC descriptor";
case 0x0D: return "DSM CC section";
case 0x0E: return "MPEG2 aux";
case 0x0F: return "ADTS";
case 0x10: return "MPEG4";
case 0x11: return "LATM";
case 0x12: return "SL/Flex PES";
case 0x13: return "SL/Flex section";
case 0x14: return "SDP";
case 0x15: return "meta PES";
case 0x16: return "meta section";
case 0x1B: return "H264";
case 0x81: return "AC3";
default: return "unknown";
}
}
std::string ProgramMappingEntry::streamTypeString(){
switch (streamType()){
case 0x01:
case 0x02:
case 0x09:
case 0x10:
case 0x1B: return "video";
case 0x03:
case 0x04:
case 0x11:
case 0x81:
case 0x0F: return "audio";
default: return "data";
}
}
int ProgramMappingEntry::elementaryPid(){
return ((data[1] << 8) | data[2]) & 0x1FFF;
}
int ProgramMappingEntry::ESInfoLength(){
return ((data[3] << 8) | data[4]) & 0x0FFF;
}
void ProgramMappingEntry::advance(){
if (!(*this)) {
return;
}
data += 5 + ESInfoLength();
}
ProgramMappingTable::ProgramMappingTable(){ ProgramMappingTable::ProgramMappingTable(){
strBuf.resize(4); strBuf.resize(4);
strBuf[0] = 0x47; strBuf[0] = 0x47;
@ -841,6 +969,15 @@ namespace TS {
setSectionLength(newVal * 5 + 13); setSectionLength(newVal * 5 + 13);
} }
ProgramMappingEntry ProgramMappingTable::getEntry(int index){
int dataOffset = 4 + (AdaptationField() > 1 ? AdaptationFieldLen() + 1 : 0) + getOffset();
ProgramMappingEntry res((char*)(strBuf.data() + dataOffset + 13 + getProgramInfoLength()), (char*)(strBuf.data() + dataOffset + getSectionLength()) );
for (int i = 0; i < index; i++){
res.advance();
}
return res;
}
char ProgramMappingTable::getStreamType(short index) { char ProgramMappingTable::getStreamType(short index) {
if (index > getProgramCount()) { if (index > getProgramCount()) {
return 0; return 0;
@ -901,7 +1038,7 @@ namespace TS {
} }
int ProgramMappingTable::getCRC() { int ProgramMappingTable::getCRC() {
unsigned int loc = 4 + (AdaptationField() > 1 ? AdaptationFieldLen() + 1 : 0) + getOffset() + 13 + getProgramInfoLength() + (getProgramCount() * 5); unsigned int loc = 4 + (AdaptationField() > 1 ? AdaptationFieldLen() + 1 : 0) + getOffset() + getSectionLength();
return ((int)(strBuf[loc]) << 24) | ((int)(strBuf[loc + 1]) << 16) | ((int)(strBuf[loc + 2]) << 8) | strBuf[loc + 3]; return ((int)(strBuf[loc]) << 24) | ((int)(strBuf[loc + 1]) << 16) | ((int)(strBuf[loc + 2]) << 8) | strBuf[loc + 3];
} }
@ -936,13 +1073,12 @@ namespace TS {
output << std::string(indent + 2, ' ') << "Last Section number: " << (int)getLastSectionNumber() << std::endl; output << std::string(indent + 2, ' ') << "Last Section number: " << (int)getLastSectionNumber() << std::endl;
output << std::string(indent + 2, ' ') << "PCR PID: " << getPCRPID() << std::endl; output << std::string(indent + 2, ' ') << "PCR PID: " << getPCRPID() << std::endl;
output << std::string(indent + 2, ' ') << "Program Info Length: " << getProgramInfoLength() << std::endl; output << std::string(indent + 2, ' ') << "Program Info Length: " << getProgramInfoLength() << std::endl;
output << std::string(indent + 2, ' ') << "Programs [" << getProgramCount() << "]" << std::endl; ProgramMappingEntry entry = getEntry(0);
for (int i = 0; i < getProgramCount(); i++) { while (entry) {
output << std::string(indent + 4, ' ') << "[" << i + 1 << "] "; output << std::string(indent + 4, ' ');
output << "StreamType: 0x" << std::hex << std::setw(2) << std::setfill('0') << std::uppercase << (int)getStreamType(i) << std::dec << ", "; stream_pids[entry.elementaryPid()] = entry.codec() + std::string(" ") + entry.streamTypeString();
output << "Elementary PID: " << getElementaryPID(i) << ", "; output << "Stream " << entry.elementaryPid() << ": " << stream_pids[entry.elementaryPid()] << " (" << entry.streamType() << "), InfoLen = " << entry.ESInfoLength() << std::endl;
output << "ES Info Length: " << getESInfoLength(i); entry.advance();
output << std::endl;
} }
output << std::string(indent + 2, ' ') << "CRC32: " << std::hex << std::setw(8) << std::setfill('0') << std::uppercase << getCRC() << std::dec << std::endl; output << std::string(indent + 2, ' ') << "CRC32: " << std::hex << std::setw(8) << std::setfill('0') << std::uppercase << getCRC() << std::dec << std::endl;
return output.str(); return output.str();

View file

@ -31,66 +31,69 @@ namespace TS {
///and calculating key values ///and calculating key values
class Packet { class Packet {
public: public:
//Constructors and fillers
Packet(); Packet();
~Packet(); ~Packet();
bool FromString(std::string & Data); bool FromString(std::string & Data);
bool FromPointer(const char * Data); bool FromPointer(const char * Data);
bool FromFile(FILE * data); bool FromFile(FILE * data);
//Base properties
void PID(int NewPID); void PID(int NewPID);
unsigned int PID(); unsigned int PID();
void ContinuityCounter(int NewContinuity); void continuityCounter(int NewContinuity);
int ContinuityCounter(); int continuityCounter();
void Clear();
void PCR(int64_t NewVal); void PCR(int64_t NewVal);
int64_t PCR(); int64_t PCR();
int64_t OPCR(); int64_t OPCR();
void AdaptationField(int NewVal); void AdaptationField(int NewVal);
int AdaptationField(); int AdaptationField();
int AdaptationFieldLen(); int AdaptationFieldLen();
void DefaultPAT();
void DefaultPMT();
int UnitStart();
void UnitStart(int NewVal);
int RandomAccess();
void RandomAccess(int NewVal);
int DiscontinuityIndicator();
int elementaryStreamPriorityIndicator();
int PCRFlag();
int OPCRFlag();
int splicingPointFlag();
//int transportPrivateDataFlag();
//int adaptationFieldExtensionFlag();
int BytesFree();
unsigned int getSyncByte();
unsigned int getTransportErrorIndicator();
unsigned int getPayloadUnitStartIndicator();
unsigned int getTransportPriority();
unsigned int getTransportScramblingControl(); unsigned int getTransportScramblingControl();
std::string toPrettyString(size_t indent = 0); //Flags
bool unitStart();
void unitStart(bool newVal);
bool randomAccess();
void randomAccess(bool newVal);
bool discontinuity();
bool hasPCR();
bool hasOPCR();
bool splicingPoint();
bool transportError();
bool priority();
bool ESpriority();
//Helper functions
operator bool();
bool isPMT();
void Clear();
void DefaultPAT();
void DefaultPMT();
unsigned int dataSize();
char * dataPointer();
int BytesFree();
void FillFree(std::string & PackageData);
int FillFree(const char * PackageData, int maxLen);
void AddStuffing();
//Printers and writers
std::string toPrettyString(size_t indent = 0, int detailLevel = 3);
const std::string& getStrBuf(); const std::string& getStrBuf();
const char * getBuffer(); const char * getBuffer();
const char * getPayload(); const char * getPayload();
int getPayloadLength(); int getPayloadLength();
const char * ToString(); const char * ToString();
//PES helpers
void PESVideoLeadIn(unsigned int len, unsigned long long PTS, unsigned long long offset); void PESVideoLeadIn(unsigned int len, unsigned long long PTS, unsigned long long offset);
static void PESVideoLeadIn(std::string & toSend, unsigned long long PTS, unsigned long long offset); static void PESVideoLeadIn(std::string & toSend, unsigned long long PTS, unsigned long long offset);
static std::string & getPESVideoLeadIn(unsigned int len, unsigned long long PTS, unsigned long long offset); static std::string & getPESVideoLeadIn(unsigned int len, unsigned long long PTS, unsigned long long offset);
void PESAudioLeadIn(unsigned int len, unsigned long long PTS); void PESAudioLeadIn(unsigned int len, unsigned long long PTS);
static void PESAudioLeadIn(std::string & toSend, unsigned long long PTS); static void PESAudioLeadIn(std::string & toSend, unsigned long long PTS);
static std::string & getPESAudioLeadIn(unsigned int len, unsigned long long PTS); static std::string & getPESAudioLeadIn(unsigned int len, unsigned long long PTS);
void FillFree(std::string & PackageData);
int FillFree(const char * PackageData, int maxLen);
void AddStuffing();
protected: protected:
std::string strBuf;///<The actual data std::string strBuf;///< Internal string buffer
//char Buffer[188];///< The actual data
}; };
class ProgramAssociationTable : public Packet { class ProgramAssociationTable : public Packet {
@ -117,6 +120,8 @@ namespace TS {
operator bool() const; operator bool() const;
int streamType(); int streamType();
std::string codec();
std::string streamTypeString();
int elementaryPid(); int elementaryPid();
int ESInfoLength(); int ESInfoLength();
char * ESInfo(); char * ESInfo();