FFmpeg 4.3 音视频-多路H265监控录放C++开发十三.2:avpacket中包含多个 NALU如何解析头部分析

news/2024/11/15 6:39:24 标签: ffmpeg, 音视频, c++

前提:

注意的是:我们这里是从avframe转换成avpacket 后,从avpacket中查看NALU。

在实际开发中,我们有可能是从摄像头中拿到 RGB 或者 PCM,然后将pcm打包成avframe,然后将avframe转换成avpacket,然后直接就通过网络传播avpacket了,

那么在网络传输的过程中如何传送这个avpacket呢?这就要用到 NALU 了。

关于NALU是啥?可以参考这个:

音视频开发14 FFmpeg 视频 相关格式分析 -- H264 NALU格式分析-CSDN博客

为了方便在网络上传输的一种抽象层。一般网络上传输的数据包有大小限制,而AVC(H264)的一帧大小远远大于网络传输的字节大小限制。因此要对AVC的数据流进行拆包,将一帧数据拆分为多个包传输。和NAL层相对是VAL层,即视频编码层(Video Coding Layer)

NALU就是经过分组后的一个一个数据包。

发I帧之前,⾄少要发⼀次SPS和PPS。当分辨率变化的时候,要重新发送一次SPS和PPS(类似在视频网站上,我们将分辨率从720p变成1080p的时候)

这个很重要,如果遇到我们显示不了图片或者视频的时候,应该第一个检查的就是 SPS 和PPS是否有正确的发送。

SPS:序列参数集,SPS中保存了⼀组编码视频序列(Coded video sequence)的全局参数。

PPS:图像参数集,对应的是⼀个序列中某⼀幅图像或者某⼏幅图像的参数。

I帧:帧内编码帧,可独⽴解码⽣成完整的图⽚。

P帧: 前向预测编码帧,需要参考其前⾯的⼀个I 或者B 来⽣成⼀张完整的图⽚。

B帧: 双向预测内插编码帧,则要参考其前⼀个I或者P帧及其后⾯的⼀个P帧来⽣成⼀张完整的图⽚。

每个NALU = StartCode + 由一个1字节的NALU头部 + 一个包含控制信息或编码视频数据的字节流组成。

NALU 结构单元的主体结构如下所示;⼀个原始的 H.264 NALU 单元 通常由 [StartCode] [NALU
Header] [NALU Payload] 三部分组成。

Start Code ⽤于标示这是⼀个 NALU 单元的开始,
必须是"00 00 00 01" 或 "00 00 01" ,
H.264 标准指出,当数据流是储存在介质上时,在每个 NALU 前添加起始码: 0x000001 或
0x00000001 ,⽤来指示⼀个 NALU 的起始和终⽌位置:
在这样的机制下,在码流中检测起始码,作为⼀个 NALU 得起始标识,当检测到下⼀个起始码时,当前NALU 结束。
3 字节的 0x000001 只有⼀种场合下使⽤,就是⼀个完整的帧被编为多个 slice (⽚)的时
候,包含这些 slice 的 NALU 使⽤ 3 字节起始码。其余场合都是 4 字节 0x00000001 的。
NALU Header :
NALU Header占位8Bit,其中三个字段分别为

F 为禁⽌位,占 1bit  
forbidden_zero_bit: 在 H.264 规范中规定了这⼀位必须为 0。
R为重要性指示位,占 2个 bit 
nal_ref_idc :取 00~11, 似乎指示这个 NALU 的重要性 , 如 00 的 NALU 解码器可以丢弃它⽽不影响图像的回放,0 ~ 3 ,取值越⼤,表示当前 NAL 越重要,需要优先受到保护。如果当前 NAL是属于参考帧的⽚,或是序列参数集,或是图像参数集这些重要的单位时,本句法元 素必需⼤于0 。
T 为负荷 数据类型 ,占 5 bit
nal_unit_type:这个 NALU 单元的类型 ,1 ~ 12 由 H.264 使⽤, 24 ~ 31 由 H.264 以外的应⽤
其值如下:重点是 5,6,7,8
5      Coded slice of an IDR picture                                  VCL
        IDR图像的编码条带(⽚) slice_layer_without_partitioning_rbsp( )
6      Supplemental enhancement information (SEI)                     non-VCL
        辅助增强信息 (SEI)sei_rbsp( )
7      Sequence parameter set                                         non-VCL
        序列参数集 seq_parameter_set_rbsp( )
8      Picture parameter set                                          non-VCL
        图像参数集 pic_parameter_set_rbsp( )

0      Unspecified                                                    non-VCL
        未指定
1      Coded slice of a non-IDR picture                               VCL
        ⼀个⾮IDR图像的编码条带slice_layer_without_partitioning_rbsp()
2      Coded slice data partition A                                   VCL
        编码条带数据分割块A slice_data_partition_a_layer_rbsp()
3      Coded slice data partition B                                   VCL
        编码条带数据分割块B slice_data_partition_b_layer_rbsp( )
4      Coded slice data partition C                                   VCL
        编码条带数据分割块C slice_data_partition_c_layer_rbsp( )
5      Coded slice of an IDR picture                                  VCL
        IDR图像的编码条带(⽚) slice_layer_without_partitioning_rbsp( )
6      Supplemental enhancement information (SEI)                     non-VCL
        辅助增强信息 (SEI)sei_rbsp( )
7      Sequence parameter set                                         non-VCL
        序列参数集 seq_parameter_set_rbsp( )
8      Picture parameter set                                          non-VCL
        图像参数集 pic_parameter_set_rbsp( )
9      Access unit delimiter                                          non-VCL
        访问单元分隔符 access_unit_delimiter_rbsp( )
10     End of sequence                                                non-VCL
        序列结尾 end_of_seq_rbsp( )
11     End of stream                                                  non-VCL
        流结尾end_of_stream_rbsp( )
12     Filler data                                                    non-VCL
        填充数据filler_data_rbsp( )
13     Sequence parameter set extension                               non-VCL
        序列参数集扩展seq_parameter_set_extension_rbsp( )
14     Prefix NAL unit                                                non-VCL
        NAL 单元前缀
15     Subset sequence parameter set                                  non-VCL
        子集序列参数集
16     Depth parameter set                                            non-VCL
        深度参数集
17..18 Reserved                                                       non-VCL
        保留
19     Coded slice of an auxiliary coded picture without partitioning non-VCL
        未分割的辅助编码图像的编码条带slice_layer_without_partitioning_rbsp( )
20     Coded slice extension                                          non-VCL
        编码切片扩展
21     Coded slice extension for depth view components                non-VCL
        深度视图组件的编码切片扩展
22..23 Reserved                                                       non-VCL
        保留
24..31 Unspecified                                                    non-VCL
        未定义

这里只是将之前的博客弄了一部分过来,请完全阅读。

从一个avpacket中获取 NALU,解析NALU头部。

我们这里从传递的avpacket中获取NALU,并获取头部。要研究的是通过 h264编码器后,avpacket中NALU 的头部信息,看是否发送了 PPS 和 SPS 等重要信息。

如下代码中打印的 nal_unit_type 就是每个NALU 头部字节的后5位,得到这个值就可以对比5,6,7,8,看发送的是啥,有没有发送PPS,SPS等。

	///通过h264编码器后的avpacket,解析avpacket里面的NALU
					///第一个问题是 如何从 avpacket如何分离出 每个 NALU呢?
					/// 一个avpacket 的NALU  和 下一个avpacket 的NALU 是以 0001间隔
					/// 但是一个avpacket中是有多个 NALU组成的,一个avpacket之内是以 001间隔的。
					avpacketcount++;//计算总共有多少个avpacket
					unsigned char naluheader = *(avpacket->data + 4);//跳过0001个字节
					/// naluheader这一个字节 8位是这样的:第一位是禁用位; 2,3位表示该NALU的重要性,4-7位标识是个啥类型的NALU:SPS,PPS,IDR 等,
					
					int nal_unit_type = naluheader & 0X1F;
					cout << "   nal_unit_type = " << nal_unit_type;

					//然后呢一个 avpacket中可能有多个 NALU,以001间隔开的,还需要找到这些头部
					for (int i = 4; i < avpacket->size - 4; i++) //一个data中由多条nalu
					{
						if (avpacket->data[i] == 0 &&
							avpacket->data[i + 1] == 0 &&
							avpacket->data[i + 2] == 1) {   ///001
							nal_unit_type = avpacket->data[i + 3] & 0x1f;
							avpacketcount++;
							cout << "(" << nal_unit_type << ")" << flush;
						}
					}


http://www.niftyadmin.cn/n/5752830.html

相关文章

【Excel】数据透视表分析方法大全

数据透视表的最常用的功能是分类汇总&#xff0c;其实它还有很强大的数据分析功能。在数据透视表右键菜单的值显示方式中&#xff0c;可以看到有14个很实用的分析选项。 1、总计的百分比 作用&#xff1a;透视表中每一个数字&#xff08;包括汇总行、总计行&#xff09;占右…

蓝队知识浅谈(中)

声明&#xff1a;学习视频来自b站up主 泷羽sec&#xff0c;如涉及侵权马上删除文章 感谢泷羽sec 团队的教学 视频地址&#xff1a;蓝队基础之网络七层杀伤链_哔哩哔哩_bilibili 本文主要分享一些蓝队相关的知识。 一、网络杀伤链 网络杀伤链&#xff08;Cyber Kill Chain&…

Dubbo 3.x源码(25)—Dubbo服务引用源码(8)notify订阅服务通知更新

基于Dubbo 3.1&#xff0c;详细介绍了Dubbo服务的发布与引用的源码。 此前我们学习了接口级的服务引入订阅的refreshInterfaceInvoker方法&#xff0c;当时还有最为关键的notify服务通知更新的部分源码没有学习&#xff0c;本次我们来学习notify通知本地服务更新的源码。 Dubb…

前端(2)——快速入门CSS

参考&#xff1a; 罗大富 CSS 参考手册 | 菜鸟教程 CSS 参考手册 1. CSS CSS全名是层叠样式表&#xff0c;中文名层叠样式表。用于定义网页样式和布局的样式表语言。 通过 CSS&#xff0c;你可以指定页面中各个元素的颜色、字体、大小、间距、边框、背景等样式&#xff0c;…

unity 3d到idea

第一步&#xff0c;确保jdk,sdk,gradle版本一致 unity 3d的配置 idea配置 第二步&#xff0c;整个unity导出安卓项目到idea idea配置项目&#xff08;修改gradl配置&#xff09; gradle配置代码 distributionUrlhttps\://services.gradle.org/distributions/gradle-8.7-bin.z…

【大模型】prompt实践总结

文章目录 怎么才算是好的prompt设计准则基本原则精炼原则(奥卡姆剃刀准则)具体原则真实操作技巧指定角色增加fewshots列表化代码化强调需求真实迭代大模型优化情形任务的定义和评估标准似乎可以再明确一下出现了一些之前没有考虑过的特殊情况,可以重新组织语言优化Prompt来处…

真正的一站式视频出海解决方案

鬼手剪辑一直以来为广大客户提供了各种视频出海的方案&#xff0c;先后更新了视频翻译、视频翻译精校版、短剧出海、翻译配音......当然还有很多附带的小功能&#xff0c;比如硬字幕提取、去字幕等等 之前这些功能虽然也可以让用户可以在一个网站&#xff0c;解决所有剪辑需求&…

leetcode hot100【LeetCode 64.最小路径和】java实现

LeetCode 64.最小路径和 题目描述 给定一个包含非负整数的 m x n 网格 grid&#xff0c;请找出一条从左上角 (0, 0) 到右下角 (m-1, n-1) 的路径&#xff0c;使得路径上的数字之和最小。 每次只能向下或向右移动一步。 示例 1: 输入: grid [[1, 3, 1],[1, 5, 1],[4, 2, 1…