H264视频流 解析SEI信息
1. SEI的介绍
补充增强信息(Supplemental Enhancement Information)是码流范畴里面的概念,提供了向视频码流中加入信息的办法,是H.264/H.265 视频压缩标准的特性之一。SEI 有基本的特征:
-
并不是解码过程的必须项;
-
有可能对解码过程(容错、纠错)有帮助;
-
集成在视频码流中;
这意味着视频编码器在输出视频码流的时候,可以不提供SEI信息 。同时我们也要清楚:视频传输过程、解封装、解码环节,都可能因为某种原因丢弃SEI 。 在视频内容的生成端、传输过程中,都可以插入SEI 信息。插入的信息,和其他视频内容一起经过传输链路到达了消费端。那么在SEI 中可以添加哪些信息呢?这里举几个例子,用户场景可以任意扩展:
-
传递编码器参数;
-
传递视频版权信息;
-
传递摄像头参数;
-
传递内容生成过程中的剪辑事件(引发场景切换);
1.1 NAL unit类型
网络抽象层(Network Abstract Layer)简称为NAL。在H.264/AVC视频编码标准中,整个系统框架被分为了两个层面:视频编码层面(Video Coding Layer - VCL)和网络抽象层面(Network Abstraction Layer - NAL)。VCL负责表示有效视频数据的内容,NAL 负责格式化数据并提供头信息,以保证数据适合各种信道和存储介质上的传输。NAL unit是NAL的基本语法结构,它包含一个字节的头信息(NAL header)和一系列来自VCL的原始数据字节流(RBSP),
为了方便从字节流中提取出 NALU,协议规定,在每个 NALU 的前面加上起始码(StartCode): 0x000001 或 0x00000001。
NALU 组成结构
NALU(NAL Unit)= 一组对应于视频编码的 NALU 头部信息(NAL header)+ 一个 RBSP(Raw Byte Sequence Payload,原始字节序列负荷)
74f31f05c68776da6bf8fcfb43904dba.pngNALU Header 组成结构
NALU Header 由 8 bit 组成,其中最后的 5 bit 表示 NAL Unit Type,具体结构⻅下图:
6f2cd955867ac568552bd6ee5ff9ed55.pngNAL Unit Type | NAL Unit Content |
---|---|
1 | 非 IDR 图像,且不采用数据划分的片段 |
5 | IDR 图像 |
6 | 补充增强信息(SEI) |
7 | 序列参数集(SPS) |
8 | 图像参数集(PPS) |
11 | 流结束符 |
SEI payload type 计算方式
当开始解析类型为 SEI 的 NAL 时,在 RBSP 中持续读取 8 bit,直到非 0xff 为止,然后把读取的数值累加,累加值即为 SEI payload type。
08175421_634148cdbf89335366.jpeg
SEI RBSP 结构图如下:
b007b85fffa3ef9d42fd0228cdda1c37.pngSEI payload size 计算方式
读取 SEI payload size 的逻辑与 SEI payload type 类似,即读取到非 0xff 为止,这样可以支持任意⻓度的 SEI payload 添加。假设 SEI payload type 后面的字符序列是 FF FF AA BB ….,则 FF FF AA 将会解析成 SEI payload size,为 255 + 255 + 170 = 680。
08175421_634148cdd390698099.jpeg
SEI payload代表的不同含义
其中SEI payload类型值为5时,指定的处理方法叫user_data_unregistered(),字面含义为未注册的用户数据,常用于存储编码器的编码参数信息,是比较常见的payload类型
image2023-9-14_20-33-38 (1).png
通过user_data_unregistered()语法解析可以看出,当使用SEI payload type为5时,注意事项如下:
-
payload size应该大于16;
-
uuid可能出现0x000000/0x000001/0x000002,需要插入0x03做防竞争处理;
实践 视频片段:以m3u8的视频片段ts文件为例
资源地址: https://github.com/yangfangkuo/CommonFile/raw/master/test_SEI_-1694589490969.ts
https://github.com/yangfangkuo/CommonFile/raw/master/test_SEI_-1694589490969.ts
通过查找字节位为 0x000001或者0x00000001 开头的为每一个NALU模块的开头,后面跟着0x06的为SEI信息单元
所以找到图片中红色区域的片段,0x00000106代表当前是一个SEI的NALU模块
然后从RSBP里面读取SEI的payLoadType, 读取到第一个非0xFF的字节,读取到05,表示payLoadType为5,常见的还有242,代表不同的SEI解析方法,然后继续计算payload的size,读取到第一个非0xFF的字节,当前读取到的为0x1A,转换为10进制为26,表示当前的payload内容的size为26个字节
payload为5,表示从payloadContent开始,前16个字节为当前SE的uuid,后面为SEI的信息,获取10个字节,获得二进制内容转换为文本内容为“yifantest” ,字符串有结束符0x00,
image2023-9-14_20-28-0.png参考文档:https://blog.51cto.com/u_12127193/5739423
https://blog.csdn.net/Lucky_wu24/article/details/130618228