mistserver/TS_Analyser/main.cpp
2011-07-21 12:04:19 +02:00

318 lines
14 KiB
C++

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <vector>
#include <fstream>
struct program_association_table_entry {
unsigned int Program_Number;
unsigned char Reserved;
unsigned int Program_Map_PID;
};
struct program_association_table {
unsigned char Pointer_Field;
unsigned char Table_ID;
bool Section_Syntax_Indicator;
bool Zero;
unsigned char Reserved_1;
unsigned int Section_Length;
unsigned int Transport_Stream_ID;
unsigned char Reserved_2;
unsigned char Version_Number;
bool Current_Next_Indicator;
unsigned char Section_Number;
unsigned char Last_Section_Number;
std::vector<program_association_table_entry> Entries;
unsigned int CRC_32;
};
struct program_mapping_table_entry {
unsigned char Stream_Type;
unsigned char Reserved_1;
unsigned int Elementary_PID;
unsigned char Reserved_2;
unsigned int ES_Info_Length;
};
struct program_mapping_table {
unsigned char Pointer_Field;
unsigned char Table_ID;
bool Section_Syntax_Indicator;
bool Zero;
unsigned char Reserved_1;
unsigned int Section_Length;
unsigned int Program_Number;
unsigned char Reserved_2;
unsigned char Version_Number;
bool Current_Next_Indicator;
unsigned char Section_Number;
unsigned char Last_Section_Number;
unsigned char Reserved_3;
unsigned int PCR_PID;
unsigned char Reserved_4;
unsigned int Program_Info_Length;
//vector Descriptors
std::vector<program_mapping_table_entry> Entries;
unsigned int CRC_32;
};
struct adaptation_field {
unsigned char Adaptation_Field_Length;
bool Discontinuity_Indicator;
bool Random_Access_Indicator;
bool Elementary_Stream_Priority_Indicator;
bool PCR_Flag;
bool OPCR_Flag;
bool Splicing_Point_Flag;
bool Transport_Private_Data_Flag;
bool Adaptation_Field_Extension_Flag;
unsigned char Program_Clock_Reference_Base_MSB;
unsigned int Program_Clock_Reference_Base;
unsigned char PCR_Reserved;
unsigned int Program_Clock_Reference_Extension;
unsigned char Original_Program_Clock_Reference_Base_MSB;
unsigned int Original_Program_Clock_Reference_Base;
unsigned char OPCR_Reserved;
unsigned int Original_Program_Clock_Reference_Extension;
unsigned char Splice_Countdown;
unsigned char Transport_Private_Data_Length;
std::vector<unsigned char> Private_Data_Byte;
unsigned char Adaptation_Field_Extension_Length;
};
void print_pat( program_association_table PAT, bool Pointer_Field = false, std::string offset="\t" ) {
printf( "%sProgram Association Table\n", offset.c_str() );
if( Pointer_Field ) {
printf( "%s\tPointer Field:\t\t\t%X\n", offset.c_str(), PAT.Pointer_Field );
}
printf( "%s\tTable ID:\t\t\t%X\n", offset.c_str(), PAT.Table_ID );
printf( "%s\tSection Syntax Indicator:\t%d\n", offset.c_str(), PAT.Section_Syntax_Indicator );
printf( "%s\t0:\t\t\t\t%d\n", offset.c_str(), PAT.Zero );
printf( "%s\tReserved:\t\t\t%d\n", offset.c_str(), PAT.Reserved_1 );
printf( "%s\tSection Length:\t\t\t%X\n", offset.c_str(), PAT.Section_Length );
printf( "%s\tTransport Stream ID\t\t%X\n", offset.c_str(), PAT.Transport_Stream_ID );
printf( "%s\tReserved:\t\t\t%d\n", offset.c_str(), PAT.Reserved_2 );
printf( "%s\tVersion Number:\t\t\t%X\n", offset.c_str(), PAT.Version_Number );
printf( "%s\tCurrent Next Indicator:\t\t%d\n", offset.c_str(), PAT.Current_Next_Indicator );
printf( "%s\tSection Number:\t\t\t%X\n", offset.c_str(), PAT.Section_Number );
printf( "%s\tLast Section Number:\t\t%d\n\n", offset.c_str(), PAT.Last_Section_Number );
for( int i = 0; i < PAT.Entries.size(); i++ ) {
printf( "%s\tEntry %d\n", offset.c_str(), i );
printf( "%s\t\tProgram Number:\t\t%X\n", offset.c_str(), PAT.Entries[i].Program_Number );
printf( "%s\t\tReserved:\t\t%X\n", offset.c_str(), PAT.Entries[i].Reserved );
printf( "%s\t\tProgram Map PID:\t%X\n", offset.c_str(), PAT.Entries[i].Program_Map_PID );
}
printf( "\n%s\tCRC_32:\t\t\t\t%X\n", offset.c_str(), PAT.CRC_32 );
}
void fill_pat( program_association_table & PAT, unsigned char * TempChar ) {
PAT.Pointer_Field = TempChar[4];
PAT.Table_ID = TempChar[5];
PAT.Section_Syntax_Indicator = ((TempChar[6] & 0x80 ) != 0 );
PAT.Zero = (( TempChar[6] & 0x40 ) != 0 );
PAT.Reserved_1 = (( TempChar[6] & 0x30 ) >> 4 );
PAT.Section_Length = (( TempChar[6] & 0x0F ) << 8 ) + TempChar[7];
PAT.Transport_Stream_ID = (( TempChar[8] << 8 ) + TempChar[9] );
PAT.Reserved_2 = (( TempChar[10] & 0xC0 ) >> 6 );
PAT.Version_Number = (( TempChar[10] & 0x01 ) >> 1 );
PAT.Current_Next_Indicator = (( TempChar[10] & 0x01 ) != 0 );
PAT.Section_Number = TempChar[11];
PAT.Last_Section_Number = TempChar[12];
PAT.Entries.clear( );
for( int i = 0; i < PAT.Section_Length - 9; i += 4 ) {
program_association_table_entry PAT_Entry;
PAT_Entry.Program_Number = ( TempChar[13+i] << 8 ) + TempChar[14+i];
PAT_Entry.Reserved = ( TempChar[15+i] & 0xE0 ) >> 5;
PAT_Entry.Program_Map_PID = (( TempChar[15+i] & 0x1F ) << 8 ) + TempChar[16+i];
PAT.Entries.push_back( PAT_Entry );
}
PAT.CRC_32 = ( TempChar[8+PAT.Section_Length-4] << 24 ) + ( TempChar[8+PAT.Section_Length-3] << 16 ) + ( TempChar[8+PAT.Section_Length-2] << 8 ) + ( TempChar[8+PAT.Section_Length-1] );
}
void fill_pmt( program_mapping_table & PMT, unsigned char * TempChar ) {
int CurrentOffset;
PMT.Pointer_Field = TempChar[4];
PMT.Table_ID = TempChar[5];
PMT.Section_Syntax_Indicator = (( TempChar[6] & 0x80 ) != 0 );
PMT.Zero = (( TempChar[6] & 0x40 ) != 0 );
PMT.Reserved_1 = (( TempChar[6] & 0x30 ) >> 4 );
PMT.Section_Length = (( TempChar[6] & 0x0F ) << 8 ) + TempChar[7];
PMT.Program_Number = (TempChar[8] << 8) + TempChar[9];
PMT.Reserved_2 = (( TempChar[10] & 0xC0 ) >> 6 );
PMT.Version_Number = (( TempChar[10] & 0x1E ) >> 1 );
PMT.Current_Next_Indicator = ( TempChar[10] & 0x01 );
PMT.Section_Number = TempChar[11];
PMT.Last_Section_Number = TempChar[12];
PMT.Reserved_3 = (( TempChar[13] & 0xE0 ) >> 5 );
PMT.PCR_PID = (( TempChar[13] & 0x1F ) << 8 ) + TempChar[14];
PMT.Reserved_4 = (( TempChar[15] & 0xF0 ) >> 4 );
PMT.Program_Info_Length = ((TempChar[15] & 0x0F ) << 8 ) + TempChar[16];
CurrentOffset = 17 + PMT.Program_Info_Length;
PMT.Entries.clear( );
while( CurrentOffset < PMT.Section_Length - 8 ) {
program_mapping_table_entry PMT_Entry;
PMT_Entry.Stream_Type = TempChar[CurrentOffset];
PMT_Entry.Reserved_1 = (( TempChar[CurrentOffset+1] & 0xE0 ) >> 5 );
PMT_Entry.Elementary_PID = (( TempChar[CurrentOffset+1] & 0x1F ) << 8 ) + TempChar[CurrentOffset+2];
PMT_Entry.Reserved_2 = (( TempChar[CurrentOffset+3] & 0xF0 ) >> 4 );
PMT_Entry.ES_Info_Length = (( TempChar[CurrentOffset+3] & 0x0F ) << 8 ) + TempChar[CurrentOffset+4];
PMT.Entries.push_back( PMT_Entry );
CurrentOffset += 4 + PMT_Entry.ES_Info_Length;
}
PMT.CRC_32 = ( TempChar[CurrentOffset] << 24 ) + ( TempChar[CurrentOffset+1] << 16 ) + ( TempChar[CurrentOffset+2] << 8 ) + ( TempChar[CurrentOffset+3] );
}
void print_pmt( program_mapping_table PMT, bool Pointer_Field = false, std::string offset="\t" ) {
if( Pointer_Field ) {
printf( "%s\tPointer Field:\t\t\t%X\n", offset.c_str(), PMT.Pointer_Field );
}
printf( "%s\tTable ID:\t\t\t%X\n", offset.c_str(), PMT.Table_ID );
printf( "%s\tSection Syntax Indicator:\t%d\n", offset.c_str(), PMT.Section_Syntax_Indicator);
printf( "%s\t0:\t\t\t\t%d\n", offset.c_str(), PMT.Zero );
printf( "%s\tReserved:\t\t\t%d\n", offset.c_str(), PMT.Reserved_1 );
printf( "%s\tSection Length:\t\t\t%X\n", offset.c_str(), PMT.Section_Length );
printf( "%s\tProgram Number:\t\t\t%X\n", offset.c_str(), PMT.Program_Number );
printf( "%s\tReserved:\t\t\t%d\n", offset.c_str(), PMT.Reserved_2 );
printf( "%s\tVersion Number:\t\t\t%d\n", offset.c_str(), PMT.Version_Number );
printf( "%s\tCurrent_Next_Indicator:\t\t%d\n", offset.c_str(), PMT.Current_Next_Indicator );
printf( "%s\tSection Number:\t\t\t%d\n", offset.c_str(), PMT.Section_Number );
printf( "%s\tLast Section Number:\t\t%d\n", offset.c_str(), PMT.Last_Section_Number );
printf( "%s\tReserved:\t\t\t%d\n", offset.c_str(), PMT.Reserved_3 );
printf( "%s\tPCR PID:\t\t\t%X\n", offset.c_str(), PMT.PCR_PID );
printf( "%s\tReserved:\t\t\t%d\n", offset.c_str(), PMT.Reserved_4 );
printf( "%s\tProgram Info Length:\t\t%d\n", offset.c_str(), PMT.Program_Info_Length );
printf( "%s\tProgram Descriptors Go Here\n\n" );
for( int i = 0; i < PMT.Entries.size(); i++ ) {
printf( "%s\tEntry %d:\n", offset.c_str(), i );
printf( "%s\t\tStream Type\t\t%d\n", offset.c_str(), PMT.Entries[i].Stream_Type );
printf( "%s\t\tReserved\t\t%d\n", offset.c_str(), PMT.Entries[i].Reserved_1 );
printf( "%s\t\tElementary PID\t\t%X\n", offset.c_str(), PMT.Entries[i].Elementary_PID );
printf( "%s\t\tReserved\t\t%d\n", offset.c_str(), PMT.Entries[i].Reserved_2 );
printf( "%s\t\tES Info Length\t\t%d\n", offset.c_str(), PMT.Entries[i].ES_Info_Length );
}
printf( "%s\tCRC 32\t\t%X\n", offset.c_str(), PMT.CRC_32 );
}
void fill_af( adaptation_field & AF, unsigned char * TempChar ) {
AF.Adaptation_Field_Length = TempChar[4];
AF.Discontinuity_Indicator = (( TempChar[5] & 0x80 ) >> 7 );
AF.Random_Access_Indicator = (( TempChar[5] & 0x40 ) >> 6 );
AF.Elementary_Stream_Priority_Indicator = (( TempChar[5] & 0x20 ) >> 5 );
AF.PCR_Flag = (( TempChar[5] & 0x10 ) >> 4 );
AF.OPCR_Flag = (( TempChar[5] & 0x08 ) >> 3 );
AF.Splicing_Point_Flag = (( TempChar[5] & 0x04 ) >> 2 );
AF.Transport_Private_Data_Flag = (( TempChar[5] & 0x02 ) >> 1 );
AF.Adaptation_Field_Extension_Flag = (( TempChar[5] & 0x01 ) );
int CurrentOffset = 6;
if( AF.PCR_Flag ) {
AF.Program_Clock_Reference_Base_MSB = ( ( ( TempChar[CurrentOffset] ) & 0x80 ) >> 7 );
AF.Program_Clock_Reference_Base = ( ( ( TempChar[CurrentOffset] ) & 0x7F ) << 25 );
AF.Program_Clock_Reference_Base += ( ( TempChar[CurrentOffset+1] ) << 17 );
AF.Program_Clock_Reference_Base += ( ( TempChar[CurrentOffset+2] ) << 9 );
AF.Program_Clock_Reference_Base += ( ( ( TempChar[CurrentOffset+3] ) & 0x80 ) >> 7 );
AF.PCR_Reserved = ( ( TempChar[CurrentOffset+3] ) & 0x7E ) >> 1;
AF.Program_Clock_Reference_Extension = ( ( TempChar[CurrentOffset+3] ) & 0x01 ) << 8 + TempChar[CurrentOffset+4];
CurrentOffset += 5;
}
}
void print_af( adaptation_field AF, std::string offset="\t" ) {
printf( "%sAdaptation Field\n", offset.c_str() );
printf( "%s\tAdaptation Field Length\t\t\t%X\n", offset.c_str(), AF.Adaptation_Field_Length );
printf( "%s\tDiscontinuity Indicator\t\t\t%X\n", offset.c_str(), AF.Discontinuity_Indicator );
printf( "%s\tRandom Access Indicator\t\t\t%X\n", offset.c_str(), AF.Random_Access_Indicator );
printf( "%s\tElementary Stream Priority Indicator\t%X\n", offset.c_str(), AF.Elementary_Stream_Priority_Indicator );
printf( "%s\tPCR Flag\t\t\t\t%X\n", offset.c_str(), AF.PCR_Flag );
printf( "%s\tOPCR Flag\t\t\t\t%X\n", offset.c_str(), AF.OPCR_Flag );
printf( "%s\tSplicing Point Flag\t\t\t%X\n", offset.c_str(), AF.Splicing_Point_Flag );
printf( "%s\tTransport Private Data Flag\t\t%X\n", offset.c_str(), AF.Transport_Private_Data_Flag );
printf( "%s\tAdaptation Field Extension Flag\t\t%X\n", offset.c_str(), AF.Adaptation_Field_Extension_Flag );
if( AF.PCR_Flag ) {
printf( "\n%s\tProgram Clock Reference Base\t\t%X%X\n", offset.c_str(), AF.Program_Clock_Reference_Base_MSB, AF.Program_Clock_Reference_Base );
printf( "%s\tReserved\t\t\t\t%d\n", offset.c_str(), AF.PCR_Reserved );
printf( "%s\tProgram Clock Reference Extension\t%X\n", offset.c_str(), AF.Program_Clock_Reference_Extension );
}
}
int find_pid_in_pat( program_association_table PAT, unsigned int PID ) {
for( int i = 0; i < PAT.Entries.size(); i++ ) {
if( PAT.Entries[i].Program_Map_PID == PID ) {
return PAT.Entries[i].Program_Number;
}
}
return -1;
}
int main( ) {
std::string File;
unsigned int BlockNo = 1;
unsigned int EmptyBlocks = 0;
unsigned char TempChar[188];
unsigned char Skip;
unsigned int SkippedBytes = 0;
unsigned int Adaptation;
program_association_table PAT;
program_mapping_table PMT;
adaptation_field AF;
int ProgramNum;
while( std::cin.good( ) && BlockNo <= 10000) {
for( int i = 0; i < 188; i++ ) {
if( std::cin.good( ) ){ TempChar[i] = std::cin.get(); }
}
if( ( ( TempChar[1] & 0x1F ) << 8 ) + ( TempChar[2] ) != 0x1FFF ) {
printf( "Block %d:\n", BlockNo );
printf( "\tSync Byte:\t\t\t%X\n", TempChar[0] );
printf( "\tTransport Error Indicator:\t%d\n", ( ( TempChar[1] & 0x80 ) != 0 ) );
printf( "\tPayload Unit Start Indicator:\t%d\n", ( ( TempChar[1] & 0x40 ) != 0 ) );
printf( "\tTransport Priority:\t\t%d\n", ( ( TempChar[1] & 0x20 ) != 0 ) );
printf( "\tPID:\t\t\t\t%X\n", ( ( TempChar[1] & 0x1F ) << 8 ) + ( TempChar[2] ) );
printf( "\tScrambling control:\t\t%d\n", ( ( TempChar[3] & 0xC0 ) >> 6 ) );
printf( "\tAdaptation Field Exists:\t%d\n", ( ( TempChar[3] & 0x30 ) >> 4 ) );
printf( "\tContinuity Counter:\t\t%X\n", ( TempChar[3] & 0x0F ) );
Adaptation = ( ( TempChar[3] & 0x30 ) >> 4 );
//Adaptation Field Exists
if( Adaptation == 2 || Adaptation == 3 ) {
fill_af( AF, TempChar );
print_af( AF );
}
if( ( ( ( TempChar[1] & 0x1F ) << 8 ) + TempChar[2] ) == 0 ) {
fill_pat( PAT, TempChar );
print_pat( PAT, true );
}
ProgramNum = find_pid_in_pat( PAT, ( ( TempChar[1] & 0x1F ) << 8 ) + ( TempChar[2] ) );
if( ProgramNum != -1 ) {
printf( "\tProgram Mapping Table for program %X\n", ProgramNum );
fill_pmt( PMT, TempChar );
print_pmt( PMT, true );
}
BlockNo ++;
} else {
EmptyBlocks ++;
}
//Find Next Sync Byte
SkippedBytes = 0;
while( (int)std::cin.peek( ) != 0x47 ) {
std::cin >> Skip;
SkippedBytes ++;
}
}
return 0;
}