给公司的直播推流框架加上了携带SEI的功能,做完了记录一下
这个东西使用场景挺广的,比如直播中的动画效果,直接渲染到画面上可能会引起性能消耗,不如通过SEI告诉给观众,由观众端做出UI响应,既能保持直播画面和效果同步出现,又能减少主播端的性能消耗,其次,对于音频视频文件资源,可以通过SEI在视频中埋入版权等信息。
H264编码由两个部分组成(VCL和NAL)
画面帧首先要经过 视频编码层面(VCL) 被编码层切割成宏块,这不是本篇记录的重点,不展开讲
之后这些块会被 网络抽象层面(NAL) 分割成多个NALU块
NAL NAL NAL NAL …
这些NAL块里一部分是装着上面切割的画面数据,一部分装着描述这个视频的参数数据(输序列参数集和图像参数集等等)
接着拆
每个NAL又可以拆成NAL Header和RBSP
NAL Header RBSP NAL Header RBSP …
其中NAL Header描述了这个NAL的类型及携带了什么样的参数,RBSP则是这个NAL携带的内容
NAL Header的位图如下
NAL Header 摘自go_str博客
1、F(forbiden):禁止位,占用NAL头的第一个位,当禁止位值为1时表示语法错误;
2、NRI:参考级别,占用NAL头的第二到第三个位;值越大,该NAL越重要。
3、Type:Nal单元数据类型,也就是标识该NAL单元的数据类型是哪种,占用NAL头的第四到第8个位;
(摘自go_str博客)
其中我们比较关注的是其中的后5位,即NAL Type
nal_type 摘自go_str博客
其中Type = 6 表示该NAL携带的是辅助增强信息(SEI)
由上面NAL Header的位图可知,Type=6时,NAL Header的 头是
00 00 00 01 06
NAL起始(start code) NAL Type
接下来是SEL的参数,SEI信息包含几个主要要素
· SEI payload type (该SEI遵循的语法)
· SEI payload size (该SEI所携带信息的长度)
这里我们只讨论SEI payloadType = 5的情况,即遵循user_data_unregistered()语法的SEI信息
· SEI payload uuid (SEI)
· SEI payload content
以及作为结尾的
· rbsp trailing bits (0x80)
一个个来讲,首先是SEI payload type
他的解析方式为,持续读取8bit,直到非0xff为止,然后把读取的数值累加,累加值即为SEI payload type。
payload type 摘自金山云
接在SEI payload type 后面的,即SEI payload size,读取SEI payload size和payload type逻辑类似,仍然是读取到非0xff为止,这样可以支持任意长度的SEI payload添加。
那么按照以上逻辑,再拼上start code和NAL Type
00 00 00 01 06 05 12
___________ __ —— __
NAL起始(start code) NAL Type SEIPayloadType SEIPayloadSize
即 00 00 00 01 06 05
以上就是一个遵循user_data_unregistered()语法、payloadContent长度为18byte的SEI参数定义
定义好参数接下来就是内容部分
首先user_data_unregistered()语法要求在SEI payload size之后的16byte作为SEI payload uuid,该uuid由用户自定义,可以作为业务的标识参数
01 02 03 04 01 02 03 04 01 02 03 04 01 02 03 04
因为uuid固定为16,所以SEI payload size的长度必须大于等于16
然后就是SEI payload content,自由发挥,不要超过(content size - 16)即可,以0x00作为字符串结尾,
05 00
因为上面定义的size = 18 ,所以这里只有2byte作为content
最后再给这条NAL拼上结束标示
80
综上所致,该条NAL的完整样式即为
00 00 00 01 06 05 12 01
02 03 04 01 02 03 04 01
02 03 04 01 02 03 04 05
00 80
到这里本篇的学习记录就结束了
作者:码痞
链接:https://www.jianshu.com/p/7c6861f0d7fd
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。