• 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填写如下:

    		body[i++] = 0x03; // numOfArrays
    		body[i++] = 0x20; // configurationVersion
    		body[i++] = 0x00; // configurationVersion
    		body[i++] = 0x01; // configurationVersion
    		// vps data length 
    		body[i++] = lpMetaData->nVpsLen>>8&0xff;
    		body[i++] = lpMetaData->nVpsLen&0xff;
    		// vps data
    		memcpy(&body[i],lpMetaData->Vps,lpMetaData->nVpsLen);
    		i= i+lpMetaData->nVpsLen;
    		body[i++] = 0x21; // configurationVersion
    		body[i++] = 0x00; // configurationVersion
    		body[i++] = 0x01; // configurationVersion
    		// sps data length
    		body[i++] = lpMetaData->nSpsLen>>8&0xff;;
    		body[i++] = lpMetaData->nSpsLen&0xff;
    		// sps data
    		memcpy(&body[i],lpMetaData->Sps,lpMetaData->nSpsLen);
    		i= i+lpMetaData->nSpsLen;
    		body[i++] = 0x22; // configurationVersion
    		body[i++] = 0x00; // configurationVersion
    		body[i++] = 0x01; // configurationVersion
    		// pps data length 
    		body[i++] = lpMetaData->nPpsLen>>8&0xff;
    		body[i++] = lpMetaData->nPpsLen&0xff;
    		// pps data
    		memcpy(&body[i],lpMetaData->Pps,lpMetaData->nPpsLen);
    		i= i+lpMetaData->nPpsLen;
    

    我们了解了HEVCDecoderConfigurationRecord结构:

    typedef struct HEVCDecoderConfigurationRecord {
    	uint8_t  configurationVersion;
    	uint8_t  general_profile_space;
    	uint8_t  general_tier_flag;
    	uint8_t  general_profile_idc;
    	uint32_t general_profile_compatibility_flags;
    	uint64_t general_constraint_indicator_flags;
    	uint8_t  general_level_idc;
    	uint16_t min_spatial_segmentation_idc;
    	uint8_t  parallelismType;
    	uint8_t  chromaFormat;
    	uint8_t  bitDepthLumaMinus8;
    	uint8_t  bitDepthChromaMinus8;
    	uint16_t avgFrameRate;
    	uint8_t  constantFrameRate;
    	uint8_t  numTemporalLayers;
    	uint8_t  temporalIdNested;
    	uint8_t  lengthSizeMinusOne;
    	uint8_t  numOfArrays;
    	HVCCNALUnitArray *array;
    } HEVCDecoderConfigurationRecord;
    

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

    typedef struct HVCCNALUnitArray {
    	uint8_t  array_completeness;
    	uint8_t  NAL_unit_type;
    	uint16_t numNalus;
    	uint16_t *nalUnitLength;
    	uint8_t  **nalUnit;
    } HVCCNALUnitArray;
    

    如VPS填写如下:

    		body[i++] = 0x20; // configurationVersion
    		body[i++] = 0x00; // configurationVersion
    		body[i++] = 0x01; // configurationVersion
    		// vps data length 
    		body[i++] = lpMetaData->nVpsLen>>8&0xff;
    		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服务器,能够完美应用于各种行业的直播需求,手机直播、桌面直播、摄像机直播、课堂直播等等方面!

  • 相关阅读:
    Jquery 复习练习(01)
    web前段 弹出小例子
    MacBook 显示隐藏文件夹命令
    sqlserver 纵横
    C#获取当前页面的url
    C# Json 转对象
    jquery导航栏
    AJAX
    hao dongxi
    微信网页获取openId
  • 原文地址:https://www.cnblogs.com/babosa/p/11124022.html
Copyright © 2020-2023  润新知