EasyRTMP推送扩展支持HEVC(H265) RTMP推送之Metadata结构填写详解

我们在《EasyNVR摄像机网页直播中,推流组件EasyRTMP推送RTMP扩展支持HEVC(H.265)的方案》中描述了关于EasyRTMP进行RTMP HEVC(H.265)推流的概括性实现描述,其中,对于Metadata数据结构,很多流媒体开发者还存在不清楚的地方,这里对RTMP推送Metadata的结构进行详解。

首先, 我们先讲解下 H.264/AVC metadata 语法,方便大家理解,这相关的文章大家在网上很容易找到,如果大家比较熟悉可以跳过;
参考:《ISO/IEC 14496-15 NAL unit structured video》AVCDecoderConfigurationRecord结构:(最小长度7字节)
EasyNVR支持H.265

说明:
libEasyRTMP我们称之为Metadata,而在FFmpeg中,则称之为extradata,extradata解析,详见ff_h264_decode_extradata()

注意:
第5字节的最后2位,表示的就是NAL size的字节数。在AVCC格式中,每个NAL前面都会有NAL size字段。NAL size可能是1字节、2字节或4字节(4字节较常见),解析extradata重要目的就是确认这个值。(而Annex-B格式,要split NAL,只要去探测0x000001就可以了)

H.264 metadata 示例(AVCC格式)

EasyNVR支持H.265
metadata 如上
metasize 47
05| FF NAL size: 4字节
06| E1 SPS num: 1
07| 00 1F SPS size: 31字节
09| 67 NAL type: SPS
40| 01 PPS num: 1
41| 00 05 PPS size: 5字节
42| 68 NAL type: PPS

H.265/HEVC metadata语法

参照HEVCDecoderConfigurationRecord:(最小长度23字节)
EasyNVR支持H.265
HEVC metadata 示例EasyNVR支持H.265

metadata 如上
metasize 111
24| 20 NAL type: VPS
25| 00 01 VPS num: 1
27| 00 19 VPS size: 25字节
54| 21 NAL type: SPS
55| 00 01 SPS num: 1
57| 00 29 SPS size: 41字节
100| 22 NAL type: PPS

hvcC extradata是一种头描述的格式。而annex-b格式中,则是将VPS, SPS和PPS等同于普通NAL,用start code分隔,非常简单。Annex-B格式的”extradata”:
start code+VPS+start code+SPS+start code+PPS

EasyRTMP中metadata填写VPS,SPS和PPS填写如下:

1 body[i++] = 0x03; // numOfArrays 2 body[i++] = 0x20; // configurationVersion 3 body[i++] = 0x00; // configurationVersion 4 body[i++] = 0x01; // configurationVersion 5 // vps data length 6 body[i++] = lpMetaData->nVpsLen>>8&0xff; 7 body[i++] = lpMetaData->nVpsLen&0xff; 8 // vps data 9 memcpy(&body[i],lpMetaData->Vps,lpMetaData->nVpsLen); 10 i= i+lpMetaData->nVpsLen; 11 body[i++] = 0x21; // configurationVersion 12 body[i++] = 0x00; // configurationVersion 13 body[i++] = 0x01; // configurationVersion 14 // sps data length 15 body[i++] = lpMetaData->nSpsLen>>8&0xff;; 16 body[i++] = lpMetaData->nSpsLen&0xff; 17 // sps data 18 memcpy(&body[i],lpMetaData->Sps,lpMetaData->nSpsLen); 19 i= i+lpMetaData->nSpsLen; 20 body[i++] = 0x22; // configurationVersion 21 body[i++] = 0x00; // configurationVersion 22 body[i++] = 0x01; // configurationVersion 23 // pps data length 24 body[i++] = lpMetaData->nPpsLen>>8&0xff; 25 body[i++] = lpMetaData->nPpsLen&0xff; 26 // pps data 27 memcpy(&body[i],lpMetaData->Pps,lpMetaData->nPpsLen); 28 i= i+lpMetaData->nPpsLen;

我们了解了HEVCDecoderConfigurationRecord结构:

1typedef struct HEVCDecoderConfigurationRecord { 2 uint8_t configurationVersion; 3 uint8_t general_profile_space; 4 uint8_t general_tier_flag; 5 uint8_t general_profile_idc; 6 uint32_t general_profile_compatibility_flags; 7 uint64_t general_constraint_indicator_flags; 8 uint8_t general_level_idc; 9 uint16_t min_spatial_segmentation_idc; 10 uint8_t parallelismType; 11 uint8_t chromaFormat; 12 uint8_t bitDepthLumaMinus8; 13 uint8_t bitDepthChromaMinus8; 14 uint16_t avgFrameRate; 15 uint8_t constantFrameRate; 16 uint8_t numTemporalLayers; 17 uint8_t temporalIdNested; 18 uint8_t lengthSizeMinusOne; 19 uint8_t numOfArrays; 20 HVCCNALUnitArray *array; 21} HEVCDecoderConfigurationRecord;

由于我们可以不必要关心其他的结构,所以我们从numOfArrays填写起,这里是三个数据信息结构(vps,sps,pps),numOfArrays=3,然后HVCCNALUnitArray结构进行填写数据头信息:

1typedef struct HVCCNALUnitArray { 2 uint8_t array_completeness; 3 uint8_t NAL_unit_type; 4 uint16_t numNalus; 5 uint16_t *nalUnitLength; 6 uint8_t **nalUnit; 7} HVCCNALUnitArray;

如VPS填写如下:

1 body[i++] = 0x20; // configurationVersion 2 body[i++] = 0x00; // configurationVersion 3 body[i++] = 0x01; // configurationVersion 4 // vps data length 5 body[i++] = lpMetaData->nVpsLen>>8&0xff; 6 body[i++] = lpMetaData->nVpsLen&0xff;

其他如SPS和PPS同理,见上文代码。这一点和H264 metadata结构填写是有很大的区别。

参考文章:
https://blog.csdn.net/yue_huang/article/details/75126155

EasyRTMP是TSINGSEE青犀开放平台(http://open.tsingsee.com)一套调用简单、功能完善、运行高效稳定的RTMP功能组件,经过多年实战和线上运行打造,支持RTMP推送断线重连、环形缓冲、智能丢帧、网络事件回调,支持Windows、Linux、arm(hisiv100/hisiv200/hisiv300/hisiv400/etc…)、Android、iOS平台,支持市面上绝大部分的RTMP流媒体服务器,包括Red5、Ngnix_rtmp、crtmpserver等主流RTMP服务器,能够完美应用于各种行业的直播需求,手机直播、桌面直播、摄像机直播、课堂直播等等方面!

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

swap空间的增减方法

(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap