读取并分析TS数据流
程序员文章站
2022-03-05 12:21:23
...
要求:
输出以下参数:
- TS包分组长度;
- 节目套数及对应各节目PMT PID
代码实现如下:
#include <iostream>
#include <fstream>
#include <map>
using namespace std;
struct TsHeader
{
unsigned int sync_byte;
int transport_error_indicator;
int payload_unit_start_indicator;
int transport_priority;
int PID;
short transport_scrambling_control;
short adaptation_field_control;
unsigned int continuity_counter;
int offset;
void Print()
{
cout << endl;
cout << "sync_byte: " << sync_byte << endl;
cout << "transport_priority: " << transport_priority << endl;
cout << "PID: " << PID << endl;
}
};
struct PatHeader
{
int table_id = 0;
int section_syntax_indicato = 0;
int section_length = 0;
int transport_stream_id = 0;
int version_number = 0;
int current_next_indicator = 0;
int section_number = 0;
int last_section_number = 0;
void Print()
{
cout << endl;
cout << "section_syntax_indicato: " << section_syntax_indicato << endl;
cout << "section_length: " << section_length << endl;
cout << "transport_stream_id: " << transport_stream_id << endl;
cout << "version_number: " << version_number << endl;
cout << "current_next_indicator: " << current_next_indicator << endl;
cout << "section_number: " << section_number << endl;
cout << "last_section_number: " << last_section_number << endl;
}
};
class BaseInfo
{
protected:
ifstream file;
int file_length = 0;
int package_counts;
int package_length;
int first_package_length;
public:
bool LoadFile(const string& path)
{
file.open(path, ios::binary);
if (!file.is_open())
{
cout << "Can not open " << path << endl;
return 0;
}
int pos = 0;
file.seekg(0, ios::end);
file_length = file.tellg();
file.seekg(0, ios::beg);
return 1;
}
int GetLength()
{
return file_length;
}
void CloseFIle()
{
file.close();
}
TsHeader ReadTs(unsigned char* buffer)
{
TsHeader tsh;
tsh.sync_byte = buffer[0];
tsh.transport_error_indicator = buffer[1] >> 7;
tsh.payload_unit_start_indicator = (buffer[1] & 0b01000000) >> 6;
tsh.transport_priority = (buffer[1] & 0b00100000) >> 5;
tsh.PID = ( int(buffer[1] & 0b00011111) << 8 ) + buffer[2];
tsh.transport_scrambling_control = buffer[3] >> 6;
tsh.adaptation_field_control = (buffer[3] & 0b00110000) >> 4;
tsh.continuity_counter = buffer[3] & 0b00001111;
if (tsh.adaptation_field_control == 1 || tsh.adaptation_field_control == 3)
{
if (tsh.adaptation_field_control == 1)
{
tsh.offset = 4;
if (tsh.payload_unit_start_indicator == 1)
tsh.offset += int(buffer[4]) + 1;
}
else
{
int adaption_field_length = buffer[4];
tsh.offset = adaption_field_length + 5;
if (tsh.payload_unit_start_indicator == 1)
tsh.offset += int(buffer[5]) + 1;
}
}
else tsh.offset = -1;
return tsh;
}
};
class PatReader: public BaseInfo
{
private:
bool isPatExist;
int program_num;
map<int, int> PatTable;
void CalcSyn()
{
unsigned char* buffer_408 = new unsigned char[408];
file.read((char*)buffer_408, 408);
for (int i = 0; i < 204; ++i)
{
if (buffer_408[i] == 0x47 && buffer_408[i + 188] == 0x47)
{
package_length = 188;
first_package_length = i;
break;
}
else if (buffer_408[i] == 71 && buffer_408[i + 204] == 71)
{
package_length = 204;
first_package_length = i;
break;
}
}
delete[] buffer_408;
}
void CalcPackageCounts()
{
package_counts = (file_length - first_package_length) / package_length;
}
PatHeader ReadPatHeader(unsigned char* buffer)
{
PatHeader ph;
ph.table_id = buffer[0];
ph.section_syntax_indicato = buffer[1] >> 7;
ph.section_length = (int(buffer[1] & 0x0f ) << 8) + buffer[2];
ph.transport_stream_id = (int(buffer[3]) << 8) + buffer[4];
ph.version_number = (buffer[5] & 0b00111110) >> 1;
ph.current_next_indicator = buffer[5] & 0x01;
ph.section_number = buffer[6];
ph.last_section_number = buffer[7];
return ph;
}
void GetProgram(unsigned char* buffer, int num)
{
int n = 0, pos = 0;
while ( n < num )
{
int program_number = ( int(buffer[pos]) << 8 ) + buffer[pos + 1];
int network_pid = (int(buffer[pos + 2] & 0x1f) << 8) + buffer[pos + 3];
PatTable[program_number] = network_pid;
pos += 4; n ++;
}
program_num = PatTable.size();
}
bool GetPat(unsigned char* buffer, int i)
{
int pos = 0, offset = 0;
TsHeader tsh = ReadTs(buffer);
offset = tsh.offset;
if (offset == -1 || tsh.PID != 0 ) return 0;
PatHeader ph = ReadPatHeader(buffer + offset);
if (ph.table_id) return 0;
isPatExist = 1;
int program_n = (ph.section_length - 9) / 4;
GetProgram(buffer + offset + 8, program_n);
program_num += program_n;
if (ph.section_number == ph.last_section_number)
return 1;
return 0;
}
public:
PatReader()
{
isPatExist = 0;
program_num = 0;
}
int GetPackageLength()
{
cout << "packetage length = " << package_length << " & start from = " << first_package_length << endl;
return package_length;
}
int GetPackageCounts()
{
cout << "Total package = " << package_counts << endl;
return package_counts;
}
void AnalyzePat()
{
CalcSyn();
CalcPackageCounts();
GetPackageLength();
GetPackageCounts();
file.seekg(first_package_length, ios::beg);
unsigned char* buffer = new unsigned char[package_length];
for (int i = 0; i < package_counts; ++i)
{
file.read((char*)buffer, package_length);
if (GetPat(buffer, i))
break;
}
if (isPatExist)
cout << "PAT exists!" << endl;
else return;
cout << endl << "There are " << program_num << " programs:" << endl;
cout << endl << "program\t\tPMT PID" << endl;
for (auto& i : PatTable)
cout << i.first << "\t\t" << i.second << endl;
}
} pat_reader;
int main()
{
const string path = "2.ts";
pat_reader.LoadFile(path);
pat_reader.AnalyzePat();
pat_reader.CloseFIle();
}
最终结果:
与用tsr读出来的结果相同。