当前位置: 首页 > 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(…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)

前言&#xff1a; 最近在做行为检测相关的模型&#xff0c;用的是时空图卷积网络&#xff08;STGCN&#xff09;&#xff0c;但原有kinetic-400数据集数据质量较低&#xff0c;需要进行细粒度的标注&#xff0c;同时粗略搜了下已有开源工具基本都集中于图像分割这块&#xff0c…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...