前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SkeyeRTMPPusher推送RTMP扩展支持HEVC(H265)

SkeyeRTMPPusher推送RTMP扩展支持HEVC(H265)

原创
作者头像
Openskeye
发布2023-04-23 14:07:16
2600
发布2023-04-23 14:07:16
举报

不久前刚实现SkeyeRTMPPusher扩展支持h265推送,当时在网上也查找了很多资料,发现都不尽详细,而官方也没有更新对HEVC(H265,后文统称HEVC)tag的支持,反正是走了不少弯路,当然,在广大网友以及ffmpeg代码的帮助下我最终实现了通过SkeyeRTMPPusher推送HEVC视频帧数据到SkeyeSMS,这里我将把实现过程详细的记录下来,供广大网友参考。

代码语言:txt
复制
首先, RTMP头部信息封装并没有定义HEVC,我们采用CDN联盟的HEVC扩展标准,将HEVC的VideoTagHeader定义为12,详见下图:
代码语言:txt
复制
然后,我们在H264封装的基础上进行改进,以支持HEVC头部的封装,而HEVC头有

SPS PPS VPS,我们参考ffmpeg的HEVCDecoderConfigurationRecord结构对metadata进行封装,该结构体代码如下:

代码语言:txt
复制
typedef struct HVCCNALUnitArray {
	uint8_t  array_completeness;
	uint8_t  NAL_unit_type;
	uint16_t numNalus;
	uint16_t *nalUnitLength;
	uint8_t  **nalUnit;
} HVCCNALUnitArray;

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;

参考ffmeg对该结构进行初始化如下:

代码语言:txt
复制
static void hvcc_init(HEVCDecoderConfigurationRecord *hvcc)
{
    memset(hvcc, 0, sizeof(HEVCDecoderConfigurationRecord));
    hvcc->configurationVersion = 1;
    hvcc->lengthSizeMinusOne   = 3; // 4 bytes

    /*
     * The following fields have all their valid bits set by default,
     * the ProfileTierLevel parsing code will unset them when needed.
     */
    hvcc->general_profile_compatibility_flags = 0xffffffff;
    hvcc->general_constraint_indicator_flags  = 0xffffffffffff;

    /*
     * Initialize this field with an invalid value which can be used to detect
     * whether we didn't see any VUI (in which case it should be reset to zero).
     */
    hvcc->min_spatial_segmentation_idc = MAX_SPATIAL_SEGMENTATION + 1;
}

需要注意的是,该结构其他参数我们其实可以不特别关心,我们只需要在HVCCNALUnitArray数组中把HEVC的VPS,SPS和PPS信息填入即可。

最后,填写好Metadata信息后,我们还需要在发送帧数据的时候做一下修改,将I帧的tag头改成12,P帧tag不变,设置成1即可,如下代码所示:

代码语言:txt
复制
	int i = 0;
	if(bIsKeyFrame)
	{
		//body[i++] = 0x17;// 2:Pframe  7:AVC
		body[i++] = 	 (m_metadata.nVideoCodec  == FLV_CODECID_HEVC) ? 0x1C:0x17;// 1:Iframe  7:AVC 12:HEVC

		if (m_bWaitingKeyFrame)
		{
			m_bWaitingKeyFrame = false;
		}
	}
	else
	{
		//body[i++] = 0x27;// 2:Pframe  7:AVC
		body[i++] = 	 (m_metadata.nVideoCodec  == FLV_CODECID_HEVC) ? 0x2C:0x27;// 1:Iframe  7:AVC 12:HEVC
	}
	body[i++] = 0x01;// AVC NALU
	body[i++] = 0x00;
	body[i++] = 0x00;
	body[i++] = 0x00;

	// NALU size
	body[i++] = size>>24;
	body[i++] = size>>16;
	body[i++] = size>>8;
	body[i++] = size&0xff;

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
内容分发网络 CDN
内容分发网络(Content Delivery Network,CDN)通过将站点内容发布至遍布全球的海量加速节点,使其用户可就近获取所需内容,避免因网络拥堵、跨运营商、跨地域、跨境等因素带来的网络不稳定、访问延迟高等问题,有效提升下载速度、降低响应时间,提供流畅的用户体验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com