rtmp h264,h265包结构和推流组包

3 篇文章 0 订阅

rtmp视频包结构

类型长度
FrameType4bit1表示关键帧,2表示非关键帧,3表示一次性帧,4为服务器保留,5表示视频信息或命令帧
CodecID4bit1表示JPG,2表示Sorenson H263,3表示屏幕录像,4表示VP6 ON2,,5表示带alphat通道的VP6 ON2,6表示版本2的屏幕录像,7表示avc,即h264
VideoData视频数据,根据CodecID的不同,此处字段内容不同,例如CodecID为2时,此处为H263包结构,当CodecID为7时,此处为AVC视频包结构

实际使用当中,经常用的是发送h264或者h265的包
对于h265, CodecID为7,对于h265,一般扩展的CodecID都是12
因此,对于h264视频包来说,第一个字节一般是0x17或0x27,
对于h265, 第一个字节一般是0x1c或0x2c

对于VideoData字段,当CodecID为7时,结构是AVC视频包

AVC视频包结构

类型长度
AVCPacketType8bit0表示AVC Sequence头,1表示nalu, 2一般不支持较低level的h264
Composition time3 byte如果AVCPacketType为1表示Composition time offset, 其他值是全为0
Datan byte如果AVCPacketType为0,此处是AVCDecoderConfigurationRecord,如果AVCPacketType,此处是视频数据,如果AVCPacketType为2, 此处为空

明显的,前2个字段比较明确,Composition time一般都填0
下面看下AVCDecoderConfigurationRecord

h264 AVCDecoderConfigurationRecord

参数名长度
configureVersion1 byte版本号,默认为1
AVCProfileIndication1 byteprofile定义,sps信息里面去除头部信息和sps标志后的第一个字节
profile_compatibility1 byteprofile支持级别,sps信息里面去除头部信息和sps标志后的第二个字节
AVCLevelIndication1 bytelevel级别 sps头信息之后第3个字节
reserved6 bit保留,默认为’111111’
lengthSizeMinusOne2 bitnalu unit长度 - 1,一般为3
reserved3 bit保留,默认为’111’
numOfSequenceParameterSets5 bitsps的个数,一般为1,即后面只有1个sps,如果有多个则后面2个字段循环添加
sequenceParameterSetLength2 bytesps长度,先填高8位,再填低8位
sequenceParameterSetNaluUnitn bytesps内容
numOfPictureParameterSets1 bytepps个数,一般为1,如果有多个,后面的2个字段循环添加
pictureParameterSetLength2 bytepps长度
pictureParameterSetNaLuUnitn bytepps内容

这样h264视频包结构就比较明晰了
再看看h265的HEVCDecoderConfigurationRecord

参数名长度
configureVersion1 byte版本号,默认为1
general_profile_space2 bit0, 其他值留作备用
general_tier_flag1 bit2个值,main tier和high tier,level 4和4以上支持High Tier
general_profile_idc5 bit当general_profile_space等于0时,指示CVS符合的配置文件
附件A中规定
general_profile_compatibility_flags4 byte当general_profile_idc指定的profile不在
general_constraint_indicator_flags1 byte
general_level_idc1 byte
reserved14 bit默认’1111’
min_spatial_segmentation_idc_L4 bit
min_spatial_segmentation_idc_H1 byte
reserved16 bit默认’111111’
parallelismType2 bit
reserved16 bit默认’111111’
chromaFormat2 bit
reserved15 bit默认’11111’
bitDepthLumaMinus83 bit
reserved15 bit默认’11111’
bitDepthChromaMinus83 bit
avgFrameRate2 byte
constantFrameRate2 bit
numTemporalLayers3 bit
temporalIdNested1 bit
lengthSizeMinusOne2 bit
numOfArrays1 bytevps,sps,pps个数,后续填充内容,与h264一样

librtmp 推流h265, 最开始参考的是:
https://blog.csdn.net/qq_33795447/article/details/89457581
里面的推流,用大牛那个播放器是可以播的,但是用金山修改的ffmpeg播不了
又分析了下,主要还是vps,sps,pps这些信息组包不对,
修改为下面的内容:

unsigned char body[1024] = { 0 };
	int i = 0;
	body[i++] = 0x1C;

	body[i++] = 0x00;// AVC sequence header   1byte

	body[i++] = 0x00;//composition time 3 byte
	body[i++] = 0x00;
	body[i++] = 0x00;

	body[i++] = 0x01;

	body[i++] = m_metaData.m_sps[6];
	body[i++] = m_metaData.m_sps[7];
	body[i++] = m_metaData.m_sps[8];
	body[i++] = m_metaData.m_sps[9];

	body[i++] = m_metaData.m_sps[12];
	body[i++] = m_metaData.m_sps[13];
	body[i++] = m_metaData.m_sps[14];

	body[i++] = 0x00;
	body[i++] = 0x00;
	body[i++] = 0x00;
	body[i++] = 0x00;

	body[i++] = 0x00;
	body[i++] = 0x00;
	body[i++] = 0x00;

	body[i++] = 0x00;
	body[i++] = 0x00;
	body[i++] = 0x00;

	body[i++] = 0x00;
	body[i++] = 0x00;
	body[i++] = 0x00;

	body[i++] = 0x03;	//视频数据nal长度字节数-1,只取低2位

	/* unsigned int(8) numOfArrays; 03 */
	body[i++] = 0x03;

	body[i++] = 0x20;  //vps 32
	body[i++] = 0x00;
	body[i++] = 0x01;
	body[i++] = (m_metaData.m_vpsLen >> 8) & 0xff;
	body[i++] = (m_metaData.m_vpsLen) & 0xff;
	memcpy(&body[i], m_metaData.m_vps, m_metaData.m_vpsLen);
	i += m_metaData.m_vpsLen;

	//sps
	body[i++] = 0x21; //sps 33
	body[i++] = 0x00;
	body[i++] = 0x01;
	body[i++] = (m_metaData.m_nSpsLen >> 8) & 0xff;
	body[i++] = m_metaData.m_nSpsLen & 0xff;
	memcpy(&body[i], m_metaData.m_sps, m_metaData.m_nSpsLen);
	i += m_metaData.m_nSpsLen;

	//pps
	body[i++] = 0x22; //pps 34 
	body[i++] = 0x00;
	body[i++] = 0x01;
	body[i++] = (m_metaData.m_nPpsLen >> 8) & 0xff;
	body[i++] = (m_metaData.m_nPpsLen) & 0xff;
	memcpy(&body[i], m_metaData.m_pps, m_metaData.m_nPpsLen);
	i += m_metaData.m_nPpsLen;

	memcpy(m_RTMPPacket.m_body, (unsigned char*)body, i);

下面是推流抓包获取的十六进制数据样式

1c
000000000101600000009000000000005af000fcfdf8f800000f
03
20
0001
0018
40010c01ffff01600000030090000003000003005a959809
21
0001
002f
42010101600000030090000003000003005aa006b201e1df96566924cafff0280027f0100000030010000003019080
22
0001
0007
4401c172b46240

视频包推送修改为下面的内容:

if (isKeyFrame)
	body[i++] = 0x1C;
else
	body[i++] = 0x2C;
	
body[i++] = 0x01;// AVC NALU

body[i++] = 0x00;
body[i++] = 0x00;
body[i++] = 0x00;

// NALU size
body[i++] = (size>>24) & 0xFF;
body[i++] = (size>>16) & 0xFF;
body[i++] = (size>>8) & 0xFF;
body[i++] = size&0xff;
	
	// NALU data
	memcpy(&(body[i]),packet.data,size);

下面是视频帧包样式:

1c
01
000050
00001bf9
2601ae505c889c6440bc72fcdfaa1a66cfbdb1

如果希望推流一个,多个播放,则需要在每个i帧前发送vps,sps,pps的组包
测试可以用大牛播放器,或者金山修改的ffmpeg,或者EasyPlayerPro

参考链接:
https://blog.csdn.net/SwordTwelve/article/details/89522984
https://blog.csdn.net/qq_33795447/article/details/89457581
https://blog.csdn.net/dqxiaoxiao/article/details/94820599
https://blog.csdn.net/Dillon2015/article/details/104311186
https://blog.csdn.net/yue_huang/article/details/75126155

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值