作者:保佑想-回丽水的阿卉 | 来源:互联网 | 2023-06-25 16:09
H265封装成RTP流(二H265封装成RTP流主要参考的文档为《draft-ietf-payload-rtp-h265-07.pdf》,在这个文档里面的第四章里进行
H265封装在RTP流中(2) ) )。
H265封装在RTP流中主要引用的文档为《draft-ietf-payload-rtp-h265-07.pdf》,在本文档的第四章中进行了详细描述。 H265封装在RTP数据包中,主要有四种模式。
1、将单个NAL单元软件包转换为RTP
2、多个NAL单元组成一个RTP分组
3、一个NAL单元成为多个RTP分组
4、PACI包
根据H264的封装方法和ffmpeg的内容,我们只有第一种和第三种。 由于网络的MTU大小为1500字节,所以这里选择1400字节作为一个RTP分组。 一个NAL单元在1400字节以下时,使用一个NAL单元数据包作为RTP,1400字节以上时,使用一个NAL单元作为多个RTP
staticvoidnal _ send (avformatcontext * S1,const uint8_t *buf,int size,int last ) ) ) ) ) ) ) )
{
RTPMuxContext *s=s1-priv_data;
enumavcodecidcodec=S1-streams [0]-codec-codec _ id;
av_log(S1,AV_LOG_DEBUG,' Sending NAL %x of len %d M=%d\n ',buf[0]0x1F,size,last );
if(size=s-max_payload_size ) {
int buffered _ size=s-buf _ ptr-s-buf;
int header_size;
int skip_aggregate=0;
if(codec==av_codec_id_H264 ) {
header_size=1;
skip _ aggregate=s-flags ff _ RTP _ flag _ h264 _ mod E0;
}
else
{
header_size=2;
}
//flushbufferednalunitsifthecurrentunitdoesn ' tfit
缓冲_大小2大小-最大_ payload _ size (if ) {
flush _ buffered (S1,0 );
buffered_size=0;
}
//If we aren't using mode 0,and the NAL unit fits including the
//Framing(2bytesLength,plus 1/2 bytes for the STAP-A/AP过时的丸子er )、
//writetheunittothebufferasastap-a/AP packet,otherwise flush
//and send as single NAL。
不使用/*模式0。 此NAL单元适合包含帧(长2字节,AP包)或发送单个NAL包(/
if (buffered _ size2header _ sizesize=s-max _ payload _ size
! skip_aggregate ) {
if(buffered_size==0) (
if(codec==av_codec_id_H264 ) {
*s-buf_ptr =24;
} else {
*s-buf_ptr =48 1;
*s-buf_ptr =1;
}
}
av_WB16(s-buf_ptr,size );
s-buf_ptr =2;
memcpy(s-buf_ptr,buf,size );
s-buf_ptr =size;
s-buffered_nals;
} else {
flush _ buffered (S1,0 );
ff_RTP_send_data(S1,buf,size,last );
}
} else {
int flag_byte,header_size;
flush _ buffered (S1,0 );
if (codec==av _ codec _ id _ h264 (s-flags ff _ RTP _ flag _ h264 _ mod E0 ) ) {
av_log(S1,AV_LOG_ERROR,
' NAL size %d %d,try -slice-max-size %d\n ',size,
s-max_payload_size,s-max_payload_size;
返回;
}
av_log(S1,AV_LOG_DEBUG,' NAL size %d %d\n ',size,s-max_payload_size );
if(codec==av_codec_id_H264 ) {
uint8_t type=buf[0]0x1F;
uint8_t nri=buf[0]0x60;
s-buf[0]=28; /* FU Indicator; Type=28 --- FU-A */
s-buf[0] |=nri;
s-buf[1]=type;
s-buf[1] |=1 7;
buf =1;
size -=1;
flag_byte=1;
header_size=2;
} else {
uint8_tnal_type=(buf[0]1)0x3F;
/*
* createthehevcpayloadheaderandtransmitthebufferasfragmentationunits (fu ) )。
*
* 0 1
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
*------------------------------------------------------。
*|f|type|tid |
----------------
*
* F=0
* type=49 (fragmentation单元(fu ) )
* LayerId=0
* TID=1
*/
s-buf[0]=49 1;
s-buf[1]=1;
/*
* create the FU header
*
* 0 1 2 3 4 5 6 7
------------
* |S|E| FuType |
*------------------
*
* S=variable
* E=variable
* FuType=NAL unit type
*/
s-buf[2]=nal_type;
/* set the S bit:旧式丸子as start fragment */
s-buf[2] |=1 7;
/* pass the original NAL header */
buf =2;
size -=2;
flag_byte=2;
header_size=3;
}
while (size header _ sizes-max _ payload _ size ) {
memcpy(s-buf[header_size]、buf、s-max_payload_size - header_size );
f_RTP_send_data(S1,s-buf,s-max_payload_size,0 );
buf=s-max _ payload _ size-header _ size;
size-=s-max _ payload _ size-header _ size;
s-buf[flag_byte]=~(1) 7;
}
s-buf[flag_byte] |=1 6;
memcpy(s-buf[header_size]、buf、size );
ff_RTP_send_data(S1,s-buf,size header_size,last );
}
}
注意:到目前为止还没有定义H265的payload值。 从ffmpeg的源代码来分析的话只有96。 这表示需要使用96或其他值自定义H265的payload值。
更新:该方式通过了VLC2.2.1测试。