读取并分析TS数据流

要求
输出以下参数:

  • 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[tsh.offset]) + 1;
            }
            else
            {
                int adaption_field_length = buffer[4];
                tsh.offset = adaption_field_length + 5;
                if (tsh.payload_unit_start_indicator == 1)
                    tsh.offset += int(tsh.offset) + 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++;
        }
    }
    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
        {
            delete[] buffer;
            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;
        delete[] buffer;
    }
} pat_reader;

int main()
{
    const string path = "2.ts";
    pat_reader.LoadFile(path);
    pat_reader.AnalyzePat();
    pat_reader.CloseFIle();
}

最终结果:
在这里插入图片描述
与用tsr读出来的结果相同。
tsr

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值