网站公司怎么做运营网站建设丶金手指下拉15
段老师的干货时间又到咯,下面代码实现的是将 AAC 和 H264 数据打包成 PS 包的流程,其中包括了 PES 头、PSI 表头、MPEG-TS 头、AAC/H264 数据打包等多个步骤。此外,还包含 CRC32 校验等校验码的计算。需要注意的是,此代码示例仅供参考,具体实现需要根据实际需求进行调整和修改。
#include <iostream>
 #include <fstream>
 #include <vector>
using namespace std;
// 同步字节
 const unsigned char SYNC_BYTE = 0x47;
int main() {
     ofstream out_file("output.ps", ios::out | ios::binary);
     vector<unsigned short> pid_list;
    // 打包 PAT(Program Association Table)
     PSITableHeader pat_header = {0};
     pat_header.m_table_id = 0x00;
     pat_header.m_section_syntax_indicator = true;
     pat_header.m_section_length = 13;
     out_file.write((const char*)&SYNC_BYTE, 1);
     out_file.write((const char*)&pat_header, sizeof(pat_header));
    unsigned short transport_stream_id = 1;
     unsigned short program_number = 1;
     unsigned short program_map_PID = 100;
    unsigned char section_number = 0;
     unsigned char last_section_number = 0;
    out_file.write((const char*)&transport_stream_id, 2);
     out_file.write((const char*)§ion_number, 1);
     out_file.write((const char*)&last_section_number, 1);
     out_file.write((const char*)&program_number, 2);
     out_file.write("", 3);  // 预留为 "111"
     out_file.write((const char*)&program_map_PID, 2);
     out_file.write("", 4);  // 预留为 CRC32 校验码
    PATSection pat_section = {0};
     pat_section.m_program_number = program_number;
     pat_section.m_PID = program_map_PID;
    // 打包 PMT(Program Map Table)
     PSITableHeader pmt_header = {0};
     pmt_header.m_table_id = 0x02;
     pmt_header.m_section_syntax_indicator = true;
     pmt_header.m_section_length = 13;
     out_file.write((const char*)&SYNC_BYTE, 1);
     out_file.write((const char*)&pmt_header, sizeof(pmt_header));
    unsigned char pcr_pid = 100;
     unsigned char program_info_length = 0;
    section_number = 0;
     last_section_number = 0;
    out_file.write((const char*)&program_number, 2);
     out_file.write("", 3);  // 预留为 "111"
     out_file.write((const char*)&pcr_pid, 2);
     out_file.write("", 2);  // 预留为 "1111"
     out_file.write(&program_info_length, 1);
    PMTSection pmt_section = {0};
     pmt_section.m_program_number = program_number;
     pmt_section.m_program_map_PID = program_map_PID;
     pmt_section.m_stream_types.push_back(0x1B);  // 音频类型
     pmt_section.m_stream_types.push_back(0x1B);  // 视频类型
     pmt_section.m_elementary_PIDs.push_back(0xc0);  // 音频 PID
     pmt_section.m_elementary_PIDs.push_back(0xe0);  // 视频 PID
    // 按照顺序将 PES 包和 MPEG-TS 头打包成 PS 包
     const int AAC_PACKET_SIZE = 188 - sizeof(TSHeader);  // AAC 数据包大小
     const int H264_PACKET_SIZE = 188 - sizeof(TSHeader);  // H264 数据包大小
     unsigned char aac_packet[AAC_PACKET_SIZE];
     unsigned char h264_packet[H264_PACKET_SIZE];
     int aac_packet_len = 0, h264_packet_len = 0;
    ifstream aac_file("audio.aac", ios::in | ios::binary);
     ifstream h264_file("video.h264", ios::in | ios::binary);
    while (true) {
         // 处理 AAC 数据
         aac_file.read((char*)aac_packet, AAC_PACKET_SIZE);
         aac_packet_len = aac_file.gcount();
        if (aac_packet_len == 0) {
             break;
         }
PackAACData(aac_packet, aac_packet_len, out_file);
        // 处理 H264 数据
         h264_file.read((char*)h264_packet, H264_PACKET_SIZE);
         h264_packet_len = h264_file.gcount();
        if (h264_packet_len == 0) {
             break;
         }
        PackH264Data(h264_packet, h264_packet_len, out_file, pid_list);
     }
    aac_file.close();
     h264_file.close();
    // 打包 PAT 表的 CRC32 校验码
     out_file.seekp(sizeof(SYNC_BYTE) + sizeof(pat_header) + pat_header.m_section_length - 4, ios::beg);
     unsigned int crc32 = 0xffffffff;
    for (int i = 0; i < sizeof(pat_section); i++) {
         crc32 ^= ((unsigned char*)(&pat_section))[i] << 24;
        for (int j = 0; j < 8; j++) {
             if (crc32 & 0x80000000) {
                 crc32 = (crc32 << 1) ^ 0x04c11db7;
             } else {
                 crc32 <<= 1;
             }
         }
     }
    crc32 = ~crc32;
     out_file.write((const char*)&crc32, 4);
    // 打包 PMT 表的 CRC32 校验码
     out_file.seekp(sizeof(SYNC_BYTE) + sizeof(pmt_header) + pmt_header.m_section_length - 4, ios::beg);
     crc32 = 0xffffffff;
    for (int i = 0; i < sizeof(pmt_section); i++) {
         crc32 ^= ((unsigned char*)(&pmt_section))[i] << 24;
        for (int j = 0; j < 8; j++) {
             if (crc32 & 0x80000000) {
                 crc32 = (crc32 << 1) ^ 0x04c11db7;
             } else {
                 crc32 <<= 1;
             }
         }
     }
    crc32 = ~crc32;
     out_file.write((const char*)&crc32, 4);
    // 打包 MPEG-TS 头和数据成 TS 包
     const int TS_PACKET_SIZE = 188;  // TS 数据包大小
     unsigned char ts_packet[TS_PACKET_SIZE];
     int ts_packet_len = 0;
    ifstream in_file("output.ps", ios::in | ios::binary);
     in_file.read((char*)ts_packet, 4);  // 跳过前面的 SYNC_BYTE 和 PAT 表头
     in_file.read((char*)ts_packet, TS_PACKET_SIZE);
    while (in_file.gcount() == TS_PACKET_SIZE) {
         ts_packet_len = TS_PACKET_SIZE;
        for (int i = 0; i < pid_list.size(); i++) {
             unsigned short pid = pid_list[i];
            if (ts_packet[1] >> 4 == 0x01 && (ts_packet[1] & 0x0f) == pid) {
                 TSHeader* ts_header = (TSHeader*)ts_packet;
                 ts_header->m_pid = program_map_PID;
                if (ts_header->m_adaptation_field_control == 0x02 || ts_header->m_adaptation_field_control == 0x03) {
                     int padding = TS_PACKET_SIZE - ts_packet_len - 1;
                     unsigned char* adaptation_field = ts_packet + ts_packet_len;
                     *adaptation_field++ = padding - 1;
                     memset(adaptation_field, 0xff, padding);
                     ts_packet_len += padding + 1;
                 }
                out_file.write((const char*)ts_packet, ts_packet_len);
                 break;
             }
         }
        in_file.read((char*)ts_packet, TS_PACKET_SIZE);
     }
    in_file.close();
     out_file.close();
    return 0;
 }
