欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

读取并分析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();
}

最终结果:
读取并分析TS数据流
与用tsr读出来的结果相同。
读取并分析TS数据流