当前位置: 首页 > news >正文

H264和AAC打包PS包代码

        段老师的干货时间又到咯,下面代码实现的是将 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*)&section_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;
}

相关文章:

H264和AAC打包PS包代码

段老师的干货时间又到咯&#xff0c;下面代码实现的是将 AAC 和 H264 数据打包成 PS 包的流程&#xff0c;其中包括了 PES 头、PSI 表头、MPEG-TS 头、AAC/H264 数据打包等多个步骤。此外&#xff0c;还包含 CRC32 校验等校验码的计算。需要注意的是&#xff0c;此代码示例仅供…...

Redis数据类型-ZSet

一. 概述 SortedSet又叫zset&#xff0c;它是Redis提供的特殊数据类型&#xff0c;是一种特殊的set类型&#xff0c;继承了set不可重复的特点&#xff0c;并在set基础上为每个值添加一个分数&#xff0c;用来实现值的有序排列。 二. 常用指令 明白它的特点后&#xff0c;接下来…...

国外各大学和学院对于ChatGPT使用立场总结

ChatGPT和生成式AI的快速普及对教育这个专业领域带来了威胁——全国各地的大学和学院都召开了紧急会议&#xff0c;讨论如何应对学生利用AI作弊的风险。 一部分学校和教授担心这项技术会成为学生在论文或其他写作作业和考试中寻求捷径的工具。而这种生成内容的方式往往能够绕开…...

我在VScode学Java(Java二维数组)

我的个人博客主页&#xff1a;如果\真能转义1️⃣说1️⃣的博客主页 关于Java基本语法学习---->可以参考我的这篇博客&#xff1a;(我在Vscode学Java) 接上回Java一维数组的介绍&#xff08;我在VScode学Java(Java一维数组&#xff09; &#xff09; 二维数组是Java中的一…...

HTML-iconfont动态图标SVG效果--阿里巴巴图标矢量库

给北大打工&#xff0c;实现官网首页动态图标效果_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1Ys4y1c7oh/?spm_id_from333.1007.top_right_bar_window_default_collection.content.click&vd_source924f5dad6f2dcb0a3e5dca4604287ecd&#xff08;本篇笔记操作方法…...

C++17完整导引-模板特性之编译器的if语句

编译期if语句 if constexpr 编译期if语句使用编译期if语句编译期if的注意事项编译期if影响返回值类型即使在 *then* 部分返回也要考虑 *else* 部分编译期短路求值 其他编译期if的示例完美返回泛型值使用编译期if进行类型分发 带初始化的编译期if语句在模板之外使用编译期if参考…...

告别Excel,免费大数据分析与可视化工具,让你的论文图表“高大上”

数据分析工具很多&#xff0c;可以分为表格、数据库、BI工具、编程等四大工具。每个大类又有很多的工具&#xff0c;例如表格包括Excel、WPS、Google Sheets、Airtable等。编程工具包括Python和R。 搞科研几年了&#xff0c;笔者一直都是在使用Excel做数据分析和可视化&#xf…...

C++ 中的继承和多态

C 中的继承和多态 一、继承二、函数重载、隐藏、覆盖、重写1.函数重载&#xff08;Function Overload&#xff09;2.函数隐藏&#xff08;Function Hiding&#xff09;3.函数重写与函数覆盖&#xff08;Function Override&#xff09; 三、多态四、纯虚函数和抽象类五、多重继承…...

NestedFormer:用于脑肿瘤分割的嵌套模态感知Transformer

文章目录 NestedFormer: Nested Modality-AwareTransformer for Brain Tumor Segmentation摘要方法Global Poolformer EncoderNested Modality-Aware Feature AggregationModality-Sensitive Gating 实验结果 NestedFormer: Nested Modality-AwareTransformer for Brain Tumor …...

【SQLServer】sqlserver数据库导入oracle

将sqlserver数据库导入到oracle 实用工具&#xff1a; SQL Server Management Studio 15.0.18424.0 SQL Server 管理对象 (SMO) 16.100.47021.07eef34a564af48c5b0cf0d617a65fd77f06c3eb1 Microsoft Analysis Services 客户端工具 15.0.19750.0 Microsoft 数据访问组件 (MDAC) …...

【5.20】四、性能测试—性能测试工具

目录 4.5 性能测试工具 4.5.1 LoadRunner 4.5.2 JMeter 4.5 性能测试工具 性能测试是软件测试中一个很重要的分支&#xff0c;人们为了提高性能测试的效率&#xff0c;开发出了很多性能测试工具。一款好的测试工具可以极大地提高测试效率&#xff0c;为发现软件缺陷提供重要…...

朗诵素材-《少年正是读书时》(两角色主持朗诵)

少年正是读书时 1、少年正是读书时 男&#xff1a;我们生活在/古老的土地上 男&#xff1a;我们拥有/共同的梦想 女&#xff1a;那朗朗的书声/那浓浓的墨香 女&#xff1a;都在告诉我们 合&#xff1a;少年正是&#xff0f;读书时 2、为何要读书 男&#xff1a;养心&am…...

凭借这个笔记,拿下8家大厂offer....

如何拿到多家大厂的offer&#xff0c;没有过硬的实力&#xff0c;就需要不断的学习。 我是如何拿到&#xff0c;阿里&#xff0c;腾讯&#xff0c;百度等八家大厂的offer的&#xff0c;今天我就给大家来分享我的秘密武器&#xff0c;阿里大神整理的包括&#xff0c;测试基础&am…...

介绍一下全链路压测平台的相关内容

随着互联网技术的不断发展&#xff0c;越来越多的企业开始依赖互联网来实现业务的发展和增长。而对于这些企业而言&#xff0c;如何保证他们的业务在高并发、高负载的情况下依然能够正常运行&#xff0c;是非常重要的一个问题。为了解决这个问题&#xff0c;企业可以使用全链路…...

对于无效的数据,该如何处理

一、无效数据的来源&#xff1a; 在进行数据管理时&#xff0c;无效数据是非常常见的问题。 无效数据可能来自于数据采集、输入错误、数据处理或存储错误等方面。 这些无效数据会对结果造成严重的影响&#xff0c;因此需要及时发现和处理。 二、处理无效数据&#xff1a; …...

港联证券:机器人行业有望迎来整体性机会 六氟磷酸锂翻倍上涨

表示&#xff0c;当前AI调整的时间空间已接近13年水位&#xff0c;且调整的促发因素有望缓和&#xff0c;后续可积极一些。一方面&#xff0c;13年三次调整时间在40日以内、幅度在15%以内。当前AI调整已持续1个月、幅度在10%以上&#xff0c;时空已接近历史。另一方面&#xff…...

css 伪类选择器 结构伪类

css 伪类选择器 结构伪类 常用的&#xff1a; :first-child 所有兄弟元素中的第一个 :last-child 所有兄弟元素中的最后一个 :nth-child(n) 所有兄弟元素中的第n个 :first-of-type 所有同类型兄弟元素中的第一个 :last-of-type 所有同类型兄弟元素中的最后一个 :nth-of-type(…...

常用的表格检测识别方法-表格区域检测方法(上)

常用的表格检测识别方法 表格检测识别一般分为三个子任务&#xff1a;表格区域检测、表格结构识别和表格内容识别。本章将围绕这三个表格识别子任务&#xff0c;从传统方法、深度学习方法等方面&#xff0c;综述该领域国内国外的发展历史和最新进展&#xff0c;并提供几个先进…...

【运维知识进阶篇】集群架构-Rewrite重定向

Rewrite主要实现url地址重写&#xff0c;以及重定向&#xff0c;就是把传入web的请求重定向到其他url的过程。 分以下几种场景使用 1、地址跳转&#xff0c;用户访问一个URL&#xff0c;将其定向到另一个URL 2、协议跳转&#xff0c;用户通过http协议请求网站时&#xff0c;…...

JavaScript如何使用while循环

JavaScript 中的 while 循环是一种常用的循环结构&#xff0c;用于在满足一定条件时重复执行一段代码块。while 循环会先检查条件是否为真&#xff0c;如果为真&#xff0c;则执行循环体中的代码&#xff0c;然后再次检查条件。当条件变为假时&#xff0c;循环会结束。 while(…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

【JVM面试篇】高频八股汇总——类加载和类加载器

目录 1. 讲一下类加载过程&#xff1f; 2. Java创建对象的过程&#xff1f; 3. 对象的生命周期&#xff1f; 4. 类加载器有哪些&#xff1f; 5. 双亲委派模型的作用&#xff08;好处&#xff09;&#xff1f; 6. 讲一下类的加载和双亲委派原则&#xff1f; 7. 双亲委派模…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.

ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #&#xff1a…...

Leetcode33( 搜索旋转排序数组)

题目表述 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...

前端开发者常用网站

Can I use网站&#xff1a;一个查询网页技术兼容性的网站 一个查询网页技术兼容性的网站Can I use&#xff1a;Can I use... Support tables for HTML5, CSS3, etc (查询浏览器对HTML5的支持情况) 权威网站&#xff1a;MDN JavaScript权威网站&#xff1a;JavaScript | MDN...