H.264编码解析与C++实现详解
一、H.264编码核心概念
1.1 分层编码结构
H.264采用分层设计,包含视频编码层(VCL)和网络抽象层(NAL)。VCL处理核心编码任务,NAL负责封装网络传输数据。
1.2 NALU单元结构
// NAL单元头部结构示例
struct NALHeader {uint8_t forbidden_zero_bit : 1;uint8_t nal_ref_idc : 2;uint8_t nal_unit_type : 5;
};
NAL单元类型常见值:
-
7: SPS(序列参数集)
-
8: PPS(图像参数集)
-
5: IDR帧
-
1: 非IDR帧
二、C++解析实现关键步骤
2.1 开发环境配置
使用FFmpeg库进行开发:
bash复制
# 安装FFmpeg开发库
sudo apt-get install libavformat-dev libavcodec-dev
2.2 核心代码实现
#include <libavformat/avformat.h>
#include <iostream>void parse_h264_stream(const char* filename) {AVFormatContext* fmt_ctx = nullptr;avformat_open_input(&fmt_ctx, filename, nullptr, nullptr);avformat_find_stream_info(fmt_ctx, nullptr);// 定位视频流int video_stream = -1;for (int i = 0; i < fmt_ctx->nb_streams; ++i) {if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {video_stream = i;break;}}AVPacket packet;while (av_read_frame(fmt_ctx, &packet) >= 0) {if (packet.stream_index == video_stream) {uint8_t* data = packet.data;int size = packet.size;// 解析NALU单元while (size > 0) {int nalu_size = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];data += 4;size -= 4;NALHeader header;header.forbidden_zero_bit = (data[0] >> 7) & 0x01;header.nal_ref_idc = (data[0] >> 5) & 0x03;header.nal_unit_type = data[0] & 0x1F;// 处理不同类型的NALUswitch(header.nal_unit_type) {case 7:parse_sps(data+1, nalu_size-1);break;case 8:parse_pps(data+1, nalu_size-1);break;// 其他类型处理...}data += nalu_size;size -= nalu_size;}}av_packet_unref(&packet);}avformat_close_input(&fmt_ctx);
}
2.3 参数集解析示例
void parse_sps(uint8_t* data, int size) {// 使用指数哥伦布解码int profile_idc = data[0];int constraint_flags = data[1];int level_idc = data[2];// 解析分辨率参数int width_mb = (data[3] & 0xFF) << 8 | data[4];int height_mb = (data[5] & 0xFF) << 8 | data[6];std::cout << "SPS解析结果:\n"<< "Profile: " << profile_idc << "\n"<< "Level: " << level_idc << "\n"<< "Resolution: " << (width_mb*16) << "x" << (height_mb*16)<< std::endl;
}
三、编码优化技巧
3.1 多线程编码
// 设置编码器多线程参数
AVCodecContext* codec_ctx = ...;
codec_ctx->thread_count = 4; // 使用4个编码线程
codec_ctx->thread_type = FF_THREAD_SLICE; // 基于Slice的并行
3.2 SIMD优化
在关键算法(如运动估计、DCT变换)中使用Intel AVX2指令集:
#include <immintrin.h>void dct_transform_avx2(float* block) {__m256 row0 = _mm256_load_ps(block);__m256 row1 = _mm256_load_ps(block+8);// AVX2优化计算...
}
四、开发注意事项
-
内存管理:FFmpeg使用引用计数管理内存,需正确使用
av_packet_ref/av_packet_unref。 -
时间戳处理:正确计算PTS/DTS,注意B帧带来的时序问题。
-
错误恢复:处理网络传输中的丢包情况,使用FEC或重传机制。
-
兼容性处理:针对不同设备的SPS/PPS参数进行适配。
五、性能测试对比
| 优化手段 | 1080P编码速度 | 压缩率 |
|---|---|---|
| 单线程基线 | 24fps | 1.0x |
| 多线程(4核) | 78fps | 0.99x |
| SIMD优化 | 92fps | 1.0x |
| 混合优化 | 105fps | 0.98x |
六、扩展应用方向
-
WebRTC实时通信中的H.264实现
-
硬件加速编码(Intel QSV/NVIDIA NVENC)
-
基于机器学习的率失真优化
-
AV1/H.265的兼容过渡方案
总结
本文从H.264编码原理出发,详细讲解了C++实现中的关键技术点。通过FFmpeg库的灵活运用,结合多线程和SIMD等优化手段,可构建高性能的视频处理系统。实际开发中建议参考ITU-T H.264标准文档,并结合具体应用场景进行参数调优。
相关文章:
H.264编码解析与C++实现详解
一、H.264编码核心概念 1.1 分层编码结构 H.264采用分层设计,包含视频编码层(VCL)和网络抽象层(NAL)。VCL处理核心编码任务,NAL负责封装网络传输数据。 1.2 NALU单元结构 // NAL单元头部结构示例 struc…...
Python入门(5):异常处理
目录 1 异常处理基础概念 1.1 什么是异常? 1.2 异常与错误的区别 2 异常处理基础 2.1 常见内置异常类型 2.2 try-except 基本结构 2.3 捕获多个异常 2.4 抛出异常 2.4.1 使用raise语句 2.4.2 自定义异常类 3 高级异常处理技巧 3.1 不要过度捕…...
Scala(三)
本节课学习了函数式编程,了解到它与Java、C函数式编程的区别;学习了函数的基础,了解到它的基本语法、函数和方法的定义、函数高级。。。学习到函数至简原则,高阶函数,匿名函数等。 函数的定义 函数基本语法 例子&…...
什么是 Java 泛型
一、什么是 Java 泛型? 泛型(Generics) 是 Java 中一种强大的编程机制,允许在定义类、接口和方法时使用类型参数。通过泛型,可以将数据类型作为参数传递,从而实现代码的通用性和类型安全。 简单来说&…...
Unity中根据文字数量自适应长宽的对话气泡框UI 会自动换行
使用Ugui制作一个可以根据文本数量自动调整宽度,并可以自动换行的文字UI 或者不要独立的Bg,那么一定要把bg的img设置成切片...
【小也的Java之旅系列】02 分布式集群详解
文章目录 前言为什么叫小也 本系列适合什么样的人阅读正文单体优点缺点 CAP为什么CAP不可能全部满足?CAP 三选二 分布式事务分布式方案——SeataXA模式(强一致)AT模式(自动补偿,默认模式)TCC模式࿰…...
Ubuntu里安装Jenkins
【方式1】:下载war包,直接运行,需提前搭建Java环境,要求11或17,不推荐,war包下载地址,将war包上传到服务器,直接使用命令启动 java -jar /data/jenkins/jenkins.war【方式2】&#…...
C++包管理工具vcpkg的安装使用教程
前言 使用vcpkg可以更方便地安装各种库,省去配置的时间和配置失败的风险,类似python中的anaconda,懒人必备 参考 安装参考:https://bqcode.blog.csdn.net/article/details/135831901?fromshareblogdetail&sharetypeblogde…...
微服务面试题:配置中心
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…...
Qt msvc2017程序无法用enigma vitrual box打包,用winrar打包
我们通常打包Qt程序用Enigma virtual box。这样我们的程序就可以在别的电脑上也能运行,但是有时候,我们发现Enigma virtual box在打包的时候,对于msvc2017需要编译的程序中引用webengineview模块,打包时候发现不能运行。 我们如何…...
微服务集成测试 -华为OD机试真题(A卷、JavaScript)
题目描述 现在有n个容器服务,服务的启动可能有一定的依赖性(有些服务启动没有依赖),其次,服务自身启动加载会消耗一些时间。 给你一个n n 的二维矩阵useTime,其中useTime[i][i]10表示服务i自身启动加载需…...
Springboot实战:如何用Docker和Kubernetes部署微服务
前言 随着微服务架构的普及,如何高效部署和管理这些分布式服务成为了开发者面临的重要挑战。Spring Boot凭借其简化配置、快速开发的特性,成为了构建微服务的理想框架;而Docker和Kubernetes则分别解决了服务的容器化和编排问题。本文将详细介…...
Mac: 运行python读取CSV出现 permissionError
在MAC机器里,之前一直运行程序在某个指定的目录下读取excel和csv文件,没有出现错误,有一天突然出现错误:permissionError:[Errno 1] Operation not permitted, 具体错误信息如下: 经过调查得知,…...
UE5 学习笔记 FPS游戏制作30 显示击杀信息 水平框 UI模板(预制体)
文章目录 一制作单条死亡信息框水平框的使用创建一个水平框添加子元素调整子元素顺序子元素的布局插槽尺寸填充对齐 制作UI 根据队伍,设置文本的名字和颜色声明变量 将变量设置为构造参数根据队伍,设置文本的名字和颜色在构造事件中,获取玩家…...
西门子TCP通讯过程中硬件连接突然断开
通信原理探秘又结合在工作中遇到的问题,关注到了通讯中的KeepAlive定时器的设置,所以做了如下实验。 硬件: 1513PLC TCP客户端 PC TCP服务器 前提条件:禁用PLC侧KeepAlive 程序: 测试流程: 打开PC端网络调试助手,设置为TCP服务器,打开链接; PC端打开WireShack软…...
Android学习总结之算法篇三(打家劫舍)
打家劫舍一 // 动态规划 class Solution {public int rob(int[] nums) {if (nums null || nums.length 0) return 0;if (nums.length 1) return nums[0];int[] dp new int[nums.length];dp[0] nums[0];dp[1] Math.max(dp[0], nums[1]);for (int i 2; i < nums.lengt…...
【蓝桥杯】单片机设计与开发,速成备赛
一、LED模块开看,到大模板 二、刷第零讲题目(直接复制模板) 三、空降芯片模板直接调用部分(听完再敲代码) 四、第十三讲开刷省赛题(开始自己背敲模板) 五、考前串讲刷一遍 b连接࿱…...
【操作系统】Linux进程管理和调试
在 Linux 中,可以通过以下方法查看 PID(进程ID)对应的进程名称和详细信息: 1. 使用 ps 命令(最直接) ps -p <PID> -o pid,comm,cmd示例: ps -p 1234 -o pid,comm,cmd输出: P…...
2025宁德时代测评Verify考什么?网申测评如何通过SHL笔试|附真题线上笔试考点、高分攻略、CATL新能源科技SHL测评宁德社招题目、面试攻略、求职建议
——职小豚 带你拆解新能源巨头招聘密码 一、宁德时代:新能源赛道「超级独角兽」 作为全球动力电池龙头,宁德时代(CATL)的江湖地位无需多言: 技术硬实力:麒麟电池、钠离子电池、无钴电池等黑科技加持&…...
基于 Ollama DeepSeek、Dify RAG 和 Fay 框架的高考咨询 AI 交互系统项目方案
基于 Ollama DeepSeek、Dify RAG 和 Fay 框架的高考咨询 AI 交互系统 一、项目概述 本项目旨在构建一个智能化的高考咨询助手,结合 AI 大模型、知识增强(RAG)和 3D 数字人交互,为用户提供智能高考问答、志愿填报建议、政策解读等…...
【 Vue 2 中的 Mixins 模式】
Vue 2 中的 Mixins 模式 在 Vue 2 里,mixins 是一种灵活的复用代码的方式,它能让你在多个组件间共享代码。借助 mixins,你可以把一些通用的选项(像 data、methods、computed 等)封装到一个对象里,然后在多…...
Spring Boot @RequestParam 解析参数时的常见问题及解决方案
1,遇到的问题:将后端接口写完后我想通过PostMan进行简单的测试一下,一不小心就遇到了这样的情况: org.springframework.web.bind.MissingServletRequestParameterException: Required Integer parameter contractId is not prese…...
linux xargs命令学习
命令描述 xargs从标准输入中读取默认以空格分隔的项(可以使用双引号保护空格)(或单引号或反斜杠)或换行符,并执行命令(默认为/bin/echo)一次或多次,后面跟着任何初始参数从标准输入中…...
Firefox 浏览器同步一个账户和书签网址
Firefox 浏览器同步一个账户和书签网址 Firefox 支持跨设备接续浏览,可实现电脑、手机与平板无缝衔接。无论您在使用哪台设备上使用 Firefox,都能获取书签、浏览历史、保存的密码等信息。当然也能实现windows、ios、linux、android系统中安装firefox浏览…...
Maven多模块项目,其他项目引用子模块的依赖,无法打包,提示没有找到依赖
背景: 微服务项目 每个服务都是单独的项目,会存在依赖关联的问题,在子模块的下面 depoly 之后,就会出现别的项目,无法package 原因: 多模块项目,depoly 需要在父模块下面执行...
mediacodec服务启动时加载media_codecs.xml
media.codec服务启动时, 会创建 implementation::Omx 和 implementation::OmxStore, 构造 Omx时, 会解析codec相关的xml文件,一般从会如下目录中, // from getDefaultSearchDirs() { "/product/etc",&quo…...
本地部署DeepSeek-R1(Dify压力测试和性能调优)
安装压测软件 为了有效测试,应在局域网设备测试,我这里用的服务器是局域网内的Ubuntu,下载的压测软件是WRK apt install wrk测试脚本 为了省事我直接在/root目录下新建lua脚本 vim test.lua脚本内容如下,app-xxxx更换为你工作…...
自动备份文件到服务器,自动备份文件到服务器有哪些方法?
将SQL Server数据库自动备份文件到服务器,可以通过多种方法实现。以下是几种常用的方法: 一、使用SQL Server Management Studio(SSMS)和SQL Server代理 配置SQL Server代理:确保SQL Server代理服务已启动。如果未启…...
Ollama+open-webui搭建私有本地大模型详细教程
Ollamaopen-webui搭建私有本地大模型详细教程 1. 什么是 Ollama? 1.1. Ollama 简介 Ollama 是一个轻量级的 AI 模型运行时,专注于简化 AI 模型的部署和使用。它支持多种预训练模型(如 Llama、Vicuna、Dolly 等),…...
电销行业机器人外呼话术设计:关键注意事项与实践指南
随着人工智能技术的普及,电话营销行业(电销)逐渐引入智能外呼机器人以提升效率、降低成本。然而,机器人外呼的实际效果高度依赖话术设计的合理性。若话术生硬、缺乏策略,不仅可能导致客户反感,还可能引发合…...
