
流数据
-
2023年3月18日发(作者:北京东直门医院)Rtmp数据流转h264的详细转码过程
一、目的:
这段时间,因为工作上的需要,在RTMP上做了flv流到标准h264、AAC的转换。
二、RTMP介绍:
RTMP(RealTimeMessagingProtocol)实时消息传送协议是AdobeSystems公司为
Flash播放器和服务器之间音频、视频和数据传输开发的私有协议。
RTMP协议就像一个用来装数据包的容器,这些数据可以是AMF格式的数据,也可以
是FLV中的视/音频数据.
它有三种变种:
1)工作在TCP之上的明文协议,使用端口1935;
2)RTMPT封装在HTTP请求之中,可穿越防火墙;
3)RTMPS类似RTMPT,但使用的是HTTPS连接;
Rtmp详细介绍请参照网上文档(一搜一大把)
三、Rtmp流转h264
基于rtmpclient端收取的数据包packet进行解码。
1、在rtmp传输数据流的时候,不论是在点播情况下或者直播
情况下,rtmpserver会在流开始的时候添加FileHeader和
MedadataTag。这些不需要分析。
2、数据头解析
2-1、Tagtype,一字节
每个packet的第一个字节代表了当前packet的类型。0x04表示Ping包,0x08
为audio,0x09为video。0x12为scriptdata。0x16比较特殊,这个是为了实现H.264
数据的直播而增加了一个数据类型。这个之后特别讨论。
2-2、Datasize,24bit
这三个字节表述了tag中数据段的大小。
2-3、Timestamp,24bit
记录了每一个tag相对于第一个tag(FileHeader)的相对时间。以毫秒
(milliseconds)为单位。而FileHeader的timestamp永远为0。
2-4、TimestampExtended,8bit
扩展时间字段,此字段与timestamp字段共同组成完整的时间戳字段,只不过
Timestamp是这个字段的低24位,TimestampExtended为这个字段的高8位。
2-5、StreamID,24bit
永远都是0。
2-6、Data,大小是Datasize
Tagbody。存储音视频信息等。
如果,
Tagtype==0x08,Data为audiodata。
Tagtype==0x09,Data为videodata。
Tagtype==0x12,Data为scriptdataobject。
Tagtype==0x16,Data为H264直播流数据包。
3、对rtmp音频数据的解析(audiotag)
不难看出rtmp中flv音频流就是一个接着一个的Audiotag。
每次传输流的第一个audiotag标示了音频使用的adtsheader信
息,即AACheader(audiodata),占据前3个字节。之后根据标
志位的不同,分AACsequenceheader和AACraw信息。具体解
析如下:
3-1、AACheader结构(2个字节)
3-1-1、SoundFormat,4bit
0=LinearPCM,platformendian
1=ADPCM
2=MP3
3=LinearPCM,littleendian
4=Nellymoser16kHzmono
5=Nellymoser8kHzmono
6=Nellymoser
7=G.711A-lawlogarithmicPCM
8=G.711mu-lawlogarithmicPCM
9=reserved
10=AAC
11=Speex
14=MP38kHz
15=Device-specificsound
3-1-2、SoundRate,2bit,抽样频率
0=5.5kHz
1=11kHz
2=22kHz
3=44kHz
对于aac音频来说,总是0x11,即44khz.
3-1-3、SoundSize,1bit,音频的位数。
0=8-bitsamples
1=16-bitsamples
AAC总是为0x01,16位。
3-1-4、SoundType,1bit,声道
0=Monosound
1=Stereosound
3-1-5、AACPacketType,8bit。
这个字段来表示AACAUDIODATA的类型:0=AACsequenceheader,1=AAC
raw。第一个音频包用0,后面的都用1
3-2、AACsequenceheader,2字节:
3-2-1、audioObjectType,5bit。结构编码类型
0=AACmain
1=AAClc
2=AACssr
3=AACLTP
一般AAC使用2,即AAClc
3-2-2、SamplingFrequencyIndex,4bit,音频采样率索引值
0:96000Hz
1:88200Hz
2:64000Hz
3:48000Hz
4:44100Hz
5:32000Hz
6:24000Hz
7:22050Hz
8:16000Hz
9:12000Hz
10:11025Hz
11:8000Hz
12:7350Hz
13:Reserved
14:Reserved
15:frequencyiswrittenexplicitly
通常aac固定选中44100,即应该对应为4,但是试验结果表明,当音频采样率
小于等于44100时,应该选择3,而当音频采样率为48000时,应该选择2.但是也
有例外。
3-2-3、ChannelConfiguration,4bit,音频输出声道。
对应的是音频的频道数目。单声道对应1,双声道对应2,依次类推。
0:DefinedinAOTSpecifcConfig
1:1channel:front-center
2:2channels:front-left,front-right
3:3channels:front-center,front-left,front-right
4:4channels:front-center,front-left,front-right,back-center
5:5channels:front-center,front-left,front-right,back-left,back-right
6:6channels:front-center,front-left,front-right,back-left,back-right,LFE-channel
7:8channels:front-center,front-left,front-right,side-left,side-right,back-left,
back-right,LFE-channel
8-15:Reserved
3-2-4、frameLengthConfig,1bit,标志位,用于表明IMDCT窗口长度
始终为0。
3-2-5、dependsOnCoreCoder,1bit,标志位,表明是否依赖于corecoder
始终为0。
3-2-7、extensionFlag,1bit
如果是AAC-LC,这里必须为0.
3-3、AACraw,大小不定
3-3-7、AACpayload
大小由packet的大小减去头的大小,再减去AACheader的2个字节的大小。一
般形式是,0xAF0x01+PAYLOAD.
4、对rtmp视频数据的解析(videotag)
如果packet头中的TagType==9时,就表示这个TAG是video。
那么StreamID之后的数据就表示是VideoTagHeader。
VideoTagHeader只有一个字节,也就是接跟着StreamID的1个
字节包含着视频帧类型及视频CodecID最基本信息
VideoTagHeader结构如下:
4-1、VideoTagHeader(8bit)结构:
4-1-1、FrameType,4bit,帧类型
1=keyframe(forAVC,aseekableframe)
2=interframe(forAVC,anon-seekableframe)
3=disposableinterframe(H.263only)
4=generatedkeyframe(reservedforserveruseonly)
5=videoinfo/commandframe
H264的一般为1或者2.
4-1-2、CodecID,4bit,编码类型
1=JPEG(currentlyunused)
2=SorensonH.263
3=Screenvideo
4=On2VP6
5=On2VP6withalphachannel
6=Screenvideoversion2
7=AVC
4-3、VideoData(根据CodecID判断之后videodata的类型)
IfCodecID=2,H263videopacket;
IfCodecID=3,SCREENvideopacket;
IfCodecID=4,VP6FLVvideopacket;
IfCodecID=5,VP6FLVALPHAvideopacket;
IfCodecID=6,SCREENV2videopacket;
IfCodecID=7,AVCvideopacket;
一般用AVCvideopacket。
VideoTagHeader之后跟着的就是VIDEODATA数据了,也就是videopayload.当然
就像音频AAC一样,这里也有特例就是如果视频的格式是AVC(H.264)的话,
VideoTagHeader会多出4个字节的信息。AVCPacketType和CompositionTime。
AVCPacketType表示接下来VIDEODATA(AVCVIDEOPACKET)的内容:
IFAVCPacketType==0AVCDecoderConfigurationRecord(AVCsequenceheader)
IFAVCPacketType==1OneormoreNALUs(Fullframesarerequired)
AVCDecoderConfigurationRecord.包含着是H.264解码相关比较重要的sps和pps信
息,再给AVC解码器送数据流之前一定要把sps和pps信息送出,否则的话解码器不
能正常解码。而且在解码器stop之后再次start之前,如seek、快进快退状态切换等,
都需要重新送一遍sps和pps的信息.AVCDecoderConfigurationRecord在FLV文件中一
般情况也是出现1次,也就是第一个videotag.
4-4、VIDEODATA(CodecID=7)
4-4-1、AVCPacketType,8bit
IFAVCPacketType==0AVCDecoderConfigurationRecord(AVCsequence
header)(此时FrameType必为1)
IFAVCPacketType==1OneormoreNALUs(Fullframesarerequired)
IFAVCPacketType==2AVCendofsequence(lowerlevelNALUsequence
enderisnotrequiredorsupported)
4-4-2、CompositionTime,24bit
IFAVCPacketType==1
Compositiontimeoffset,(没解析。)
ELSE
0
4-4-3、AVCDecoderConfigurationRecord(AVCPacketType==0,FrameType==1)
4-4-3-1、configurationVersion,8bit
4-4-3-2、AVCProfileIndication,8bit
4-4-3-3、profile_compatibility,8bit
4-4-3-4、AVCLevelIndication,8bit
4-4-3-5、lengthSizeMinusOne,8bit
H.264视频中NALU的长度,计算方法是1+(lengthSizeMinusOne&
3),实际测试时发现总为ff,计算结果为4.
4-4-3-6、numOfSequenceParameterSets,8bit
SPS的个数,计算方法是numOfSequenceParameterSets&0x1F,实际测
试时发现总为E1,计算结果为1
4-4-3-7、sequenceParameterSetLength,16bit
SPS的长度
4-4-3-8、sequenceParameterSetNALUnits,sps。
长度为sequenceParameterSetLength。
4-4-3-9、numOfPictureParameterSets,8bit
PPS的个数,计算方法是numOfPictureParameterSets&0x1F,实际测试
时发现总为E1,计算结果为1。
4-4-3-10、pictureParameterSetLength,16bit。
PPS的长度。
4-4-3-11、PPS
长度为pictureParameterSetLength。
4-4-4、NALUs(AVCPacketType==1,FrameType==1或者2)
一个packet里面可能包含多个NALUs,每个NALUs前的4个字节都是
标示这个NALU长度的4个字节,然后是这个NALU包。一个NALU包结束
之后,接着时下一个NALU包的长度4字节,然后是下一个NALU包。以此
类推,直到这个packet结束。
4-4-4-1、nal_length,32bit。每个nal包长度
每个NALU包前面都有(lengthSizeMinusOne&3)+1个字节的NAL
包长度描述(前文提到的,还记得吗),前面计算结果为4个字节。
4-4-4-2、nal包
这里插入一点NALU的小知识,每个NALU第一个字节的前5位标明
的是该NAL包的类型,即NALnal_unit_type
#defineNALU_TYPE_SLICE1
#defineNALU_TYPE_DPA2
#defineNALU_TYPE_DPB3
#defineNALU_TYPE_DPC4
#defineNALU_TYPE_IDR5//I帧
#defineNALU_TYPE_SEI6
#defineNALU_TYPE_SPS7
#defineNALU_TYPE_PPS8
#defineNALU_TYPE_AUD9//访问分隔符
#defineNALU_TYPE_EOSEQ10
#defineNALU_TYPE_EOSTREAM11
#defineNALU_TYPE_FILL12
四、参考文档:
1、/chef/archive/2012/07/18/
2、/liuzh501448/article/details/7245685
3、/blog/718123
4、/peijiangping1989/article/details/6934312