rv1126 SEI增强信息有关内容及嵌入方式

rv1126 SEI增强信息有关内容及嵌入方式 2024-01-08 16:50:06 1121

1.SEI简介

SEI即补充增强信息(Supplemental Enhancement Information),它提供了向视频码流中加入额外信息的方法,是H.264/H.265这些视频压缩标准的特性之一。

在视频内容的生成端和传输过程中插入SEI信息,SEI和视频内容一同经过传输链路到达消费端,消费端通过解析NAL获取对应的SEI信息,并执行相应的操作。

举例:
(1)直播问答模式,就是通过SEI传递较多和答题业务相关的信息。通过SEI承载的信息,极大地优化了题目显示和观众音视频观看的同步性。

(2)边缘AI处理,边缘端将AI推理结果放到SEI中进行传输,可以避免边缘端的视频编码,从而降低对CPU性能的需求,并且可以保证视频与推理结果的同步。

2.NAL简介

H264整个系统框架分为两层:视频编码层面(Video Coding Layer,简称VCL)和网络抽象层面(Network Abstraction Layer,简称NAL)。VCL负责表示有效视频数据的内容,NAL负责格式化数据并提供头信息,以保证数据适合各种信道和存储介质上的传输。NAL unit是NAL的基本语法结构,它包含一个字节的头信息(NAL header)和一系列来自VCL的原始数据字节流(RBSP)。

(1)H264 中 NAL unit type
NAL unit type储存在NAL header中,用一个字节表示。在H.264/AVC标准中,可用的NAL unit type一共有17种。其中值为6时表征SEI内容。比较常见的类型如下表所示

NAL unit type NAL unit content
1 非IDR图像,且不采用数据划分的片段
5 IDR图像
6 补充增强信息(SEI)
7 序列参数集(SPS)
8 图像参数集(PPS)
11 流结束符

3.SEI语法结构

名称 start code NRI payload type payload length UUID 自定义数据 结尾对齐码
数据 00 00 00 01 0x06 0x05 16+N 0x80
长度 4 1 1 M 16 N 1

说明:

1.起始码:并不固定是这个,因为一些封装格式可能会对数据包进行一些转换,上表中的起始码是标准 Annexb 格式的,而mp4以及ffmpeg读取的包,起始码的前4个字节是该帧的长度,所以可以直接判断第5个字节,当然这种方式,只能判断每一帧的开头,如果要判断该帧中都包含SPS还是PPS还是I帧,那就需要偏移然后做进一步判断,或者是用ffmpeg的filter转换成标准annexb格式。

2.payload type 为0x05,表示未注册自定义数据,这个字段不一定是单字节,也就是有可能超过255,而用两个字节表或者更多的表示,一般情况下自定义的话,用0x05就足够了。

3.payload length长度不固定,如果UUID加自定义数据的长度小于255,那该字段长度就是1字节,如果超过255,就是两个或者更多,而且每个字节的值并不是实际长度的16进制划分,而是靠起始码的字节为0xff,剩下的存在下一个字节,比如UUID加自定义数据的长度为300的话,那payload length所占的两个字节就是:0xff,0x0f,所以这个长度和type的解析都是判断是不是oxff,是的话就累加,直到出现不是0xff的数值,加上之后就是实际的有效负载的长度。另外,注意拼装sei的时候,如果长度是255,那实际也是占两个字节,分别是0xff,0x00,否则会出现长度解析错误。

下面列下payload length计算公式,假设自定义数据长度为dataLength,那么payloadLength的长度为:

payloadLength = dataLength / 0xFF + (dataLength % 0xFF != 0 ? 1 : 0);

4.SEI生成和嵌入的方式

4.1两种方式

就目前实验过的方式,下面主要看两种方式:

1.对已经有的码流作filter,插入SEI NAL(基于ffmpeg)

2.对已经有的码流结构分析,直接拼装SEI NAL,重新拼装码流帧。

详细分析:

第一种方式,该方式基于ffmpeg,使用 bsf h264_metadata filter,调用ffmpeg的接口,来嵌入sei信息,由于使用了ffmpeg的接口,鉴于底层实现,该方式也有限制,从目前的测试来看,该方式只适用于I帧,因为使用的接口要求视频帧得有SPS才行,相关底层接口代码如下:

// h264_metadata_bsf.c
static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out)
{
    H264MetadataContext *ctx = bsf->priv_data;
    AVPacket *in = NULL;
    CodedBitstreamFragment *au = &ctx->access_unit;
    int err, i, j, has_sps;
    H264RawAUD aud;
    uint8_t *displaymatrix_side_data = NULL;
    size_t displaymatrix_side_data_size = 0;
    ......
    // Only insert the SEI in access units containing SPSs, and also
    // unconditionally in the first access unit we ever see.
    if (ctx->sei_user_data && (has_sps || !ctx->done_first_au)) {
    ...
    }
    ......
}

本方式涉及的关键代码如下:

AVBSFContext *bsf;
const AVBitStreamFilter *filter;
char allcontent[] = "086f3693b7b34f2c965321492feee5b8+HelloWorld0123456789-0";

// h264 sei filter
filter = av_bsf_get_by_name("h264_metadata");
if (!filter)
{
    printf("h264_metadata bitstream filter error\n");
    goto end;
}

ret = av_bsf_alloc(filter, &bsf);
av_opt_set(bsf->priv_data, "sei_user_data", allcontent, AV_OPT_SEARCH_CHILDREN);
ret = avcodec_parameters_copy(bsf->par_in, ifmt_ctx->streams[video_index]->codecpar);
ret = av_bsf_init(bsf);
ret = avcodec_parameters_copy(ifmt_ctx->streams[video_index]->codecpar, bsf->par_out);

注意:UUID和后面自定义数据之间以 “+”号分隔,底层内部接口会根据“+”号进行解析。

第二种方式,直接拼装SEI数据包,然后嵌入到视频流中,拼装的SEI数据包也要按照前面的语法结构,否则一些测试工具是解析不出来的,如果只是考虑拼装端和解析端对应就行,那可以按照自己的协议来。

4.2测试过程

上面讨论了H264编码的视频流中嵌入sei信息的方法,实际测试过程中,发送端是基于ffmpeg方式拉取rtsp流,用上面的方法嵌入sei信息,然后推rtmp流出去,接收端将推出来的rtmp保存为flv文件,便于下面用flv工具分析。当然也可以通过代码来实现接收rtmp流并解析里面的sei信息,之所以用flv工具,是为了便于测试sei信息的规范。

5.分析录制的flv文件

将插入sei信息推送出来的rtmp流,通过ffmpeg拉取并存flv文件,然后用flv文件分析工具进行分析,查看插入的sei信息是否成功,以及是否符合规范被成功解析出来,暂时用的flvAnalyser分析工具,分析过程大概记录下:

1.打开该分析工具,将要分析的文件直接拖拽到分析工具内,如果文件很大,加载解析会需要一些时间,完成之后如下:

2.点击View下的Tag List

出现:

3.点击要查看的I帧或者P帧即可

I帧:

<长度小于255>

<长度大于255>

P帧:

<长度小于255>

<长度大于255>

说明:

左侧黄色选中的数据就是插入的sei信息,右侧是展开的解析的数据,如果sei数据包格式不对,右侧就会解析不出来。

声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包 2 1 评论 打赏
评论
1个
内容存在敏感词
手气红包
  • 李卓凡 2024-03-21 21:21:21
    回复
    不错
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区