前言

运用RTP传输H264的时候,需求用到sdp协议描绘,其间有两项:Sequence Parameter Sets (SPS) 和Picture Parameter Set (PPS)需求用到,那么这两项从哪里获取呢?答案是从H264码流中获取.在H264码流中,都是以”0x00 0x00 0x01″或许”0x00 0x00 0x00 0x01″为开端码的,找到开端码之后,运用开端码之后的第一个字节的低5位判别是否为7(sps)或许8(pps), 及data[4] & 0x1f == 7 || data[4] & 0x1f == 8.然后对获取的nal去掉开端码之后进行base64编码,得到的信息就可以用于sdp.sps和pps需求用逗号分隔开来.

起始

SDP中的H.264的SPS和PPS串,包含了初始化H.264解码器所需求的信息参数,包含编码所用的profile,level,图画的宽和高,deblock滤波器等。 由于SDP中的SPS和PPS都是BASE64编码方法的,不容易了解,附件有一个工具软件可以对SDP中的SPS和PPS进行解析。 用法是在命令行中输入:

spsparser sps.txt pps.txt output.txt

例如sps.txt中的内容为:

Z0LgFNoFglE=
pps.txt中的内容为:
aM4wpIA=

最终解析的到的成果为:

Start dumping SPS:
 profile_idc = 66
 constrained_set0_flag = 1
 constrained_set1_flag = 1
 constrained_set2_flag = 1
 constrained_set3_flag = 0
 level_idc = 20
 seq_parameter_set_id = 0
 chroma_format_idc = 1
 bit_depth_luma_minus8 = 0
 bit_depth_chroma_minus8 = 0
 seq_scaling_matrix_present_flag = 0
 log2_max_frame_num_minus4 = 0
 pic_order_cnt_type = 2
 log2_max_pic_order_cnt_lsb_minus4 = 0
 delta_pic_order_always_zero_flag = 0
 offset_for_non_ref_pic = 0
 offset_for_top_to_bottom_field = 0
 num_ref_frames_in_pic_order_cnt_cycle = 0
 num_ref_frames = 1
 gaps_in_frame_num_value_allowed_flag = 0
 pic_width_in_mbs_minus1 = 21
 pic_height_in_mbs_minus1 = 17
 frame_mbs_only_flag = 1
 mb_adaptive_frame_field_flag = 0
 direct_8x8_interence_flag = 0
 frame_cropping_flag = 0
 frame_cropping_rect_left_offset = 0
 frame_cropping_rect_right_offset = 0
 frame_cropping_rect_top_offset = 0
 frame_cropping_rect_bottom_offset = 0
 vui_parameters_present_flag = 0
​
Start dumping PPS:
 pic_parameter_set_id = 0
 seq_parameter_set_id = 0
 entropy_coding_mode_flag = 0
 pic_order_present_flag = 0
 num_slice_groups_minus1 = 0
 slice_group_map_type = 0
 num_ref_idx_l0_active_minus1 = 0
 num_ref_idx_l1_active_minus1 = 0
 weighted_pref_flag = 0
 weighted_bipred_idc = 0
 pic_init_qp_minus26 = 0
 pic_init_qs_minus26 = 0
 chroma_qp_index_offset = 10
 deblocking_filter_control_present_flag = 1
 constrained_intra_pred_flag = 0
 redundant_pic_cnt_present_flag = 0
 transform_8x8_mode_flag = 0
 pic_scaling_matrix_present_flag = 0
 second_chroma_qp_index_offset = 10

这里需求特别提一下这两个参数

pic_width_in_mbs_minus1 = 21
pic_height_in_mbs_minus1 = 17

别离表明图画的宽和高,以宏块(16×16)为单位的值减1。因此,实践的宽为 (21+1)*16 = 352

最近在做跟 h264 encode/decode 相關的研究,目標是期望可以從 Android 的 MediaRecorder 當中取出 h264 的資訊。现在問題是在於 SPS 以及 PPS 到底要怎樣得到。由於 MediaRecorder 是寫入 mp4 檔案中,所以不得已只好來去剖析一下 mp4 的檔案格局,發現沒有想像中的困難. 主要是參照 ISO/IEC 14496-15 這部份. 在 mp4 的檔案之中, 找到 avcC 這個字串, 之後便是接上 AVCDecoderConfigurationRecord. AVCDecoderConfigurationRecord 的 format 如下:

**[cpp]** [view plain](http://blog.csdn.net/pkueecser/article/details/7367641#)[copy](http://blog.csdn.net/pkueecser/article/details/7367641#)
​
1. aligned(8) class AVCDecoderConfigurationRecord { 
2.   unsigned int(8) configurationVersion = 1; 
3.   unsigned int(8) AVCProfileIndication; 
4.   unsigned int(8) profile_compatibility; 
5.   unsigned int(8) AVCLevelIndication; 
6.  
7. bit(6) reserved = '111111'b; 
8.   unsigned int(2) lengthSizeMinusOne; 
9.  
10. bit(3) reserved = '111'b; 
11.   unsigned int(5) numOfSequenceParameterSets; 
12.  
13. for (i=0; i< numOfSequenceParameterSets; i++) { 
14.    unsigned int(16) sequenceParameterSetLength ; 
15.    bit(8*sequenceParameterSetLength) sequenceParameterSetNALUnit; 
16.   } 
17.   unsigned int(8) numOfPictureParameterSets; 
18.   for (i=0; i< numOfPictureParameterSets; i++) { 
19.    unsigned int(16) pictureParameterSetLength; 
20.    bit(8*pictureParameterSetLength) pictureParameterSetNALUnit; 
21.   } 
22. } 

對照一下這樣就可以找到 SPS 和 PPS,vlc没有收到pps和sps

怎么用C言语取出H.264ES文件里的nal(sps,pps)信息。比如width, height, profile等等

解析sps,pps的代码在ffmpeg里边就有, 抄出来就行了, 我以前也自己写过…

ffmpeg的libavcodec/h264_parser.c,
h264_ps.c

函数

ff_h264_decode_seq_parameter_set
ff_h264_decode_picture_parameter_set

H.264码流第一个 NALU 是 SPS(序列参数集Sequence Parameter Set) 对应H264规范文档 7.3.2.1 序列参数集的语法进行解析

关于H264经过RTP传输的打包方法

初度尝试H264的编码经过RTP方法传输,详细试验环境的问题如下:

环境:

  • 服务器端:H264的帧数据(或许超越64k),分成N个1460字节的包,然后加上RTP头发送。
  • 客户端:VLC播映器,经过RTSP协议树立衔接,然后接收数据解码播映。

成果:

VLC不能解码接收到的数据,解码犯错,VLC的信息中显示不能解码帧数据。 我现已阅读了一遍rfc3984的文档,对里边的怎么进行打包和用rtp传输不是非常了解,期望各位大虾可以帮小弟一把,告知小弟这些和H264的帧该怎么发送,该怎么分包,该怎么加头信息等等。 (其间看到FUs的方法如同适合分包发送,由于小弟的数据帧或许超越64k,所以忘大虾们可以细心解释一下关于小弟这种情况下的RTP传输)

A:我觉得一切的问题在 RFC3984 里边都现已说得很清楚了。不知道你有哪点不懂,请详细提出来。

Q:斑竹好,我这边是用VLC和服务器端进行通讯的,他们是用RTSP协议树立 开端时的衔接的,服务器回来DISCRIBERS请求的SDP和下面描绘的相同,我运用的packetization-mode=1,即FU-As方法打 包,由于我这边上来的数据帧或许超越64k数据。能否费事斑竹看看我这边的SDP写的是否正确。

SDP:

v=0 o=- 1 1 IN IP4 127.0.0.1 s=VStream Live a=type:broadcast t=0 0 c=IN IP4 0.0.0.0 m=video 49170 RTP/AVP 99 a=rtpmap:99 H264/90000 a=fmtp:99 profile-level-id=42A01E; packetization-mode=1; sprop-parameter-ets=Z0IACpZTBYmI, aMljiA== a=control:trackID=0

还有便是在RTP发送时,我打好包的数据方法如下面所示:

上来的帧数据为:NALU头+EBSP数据

由于帧数据大于1460字节,所以我把数据分为N个不大于1460字节的包,每个包前面加上RTP头发出去。

其间NALU头的数值I帧为0x65,参数集为0x67和0x68,这个值是不是有点错误,我看RFC3984上面说的如同和我现在的有点不 同,RFC3984上面说FU-As方法打包类型值为28,我不知道这个是否十进制的,如果依照RFC3984上说的NALU头应该是多少?仍是用FU- As方法的FU indicator替代本来的NALU头。

还有这个FU-As方法的头如同是有两个值,一个是FU indicator,别的一个是FU header,这两个值我应该填写什么?

依照我现在填写的内容,VLC会呈现解不出码的情况,期望斑竹可以帮我回答的详尽一点。谢谢了。

A:我觉得 RFC3984 上面说得非常清楚啊。 首要你把一个 NALU 的 EBSP 根据需求拆分为多个包,例如 3 个,则:

  • 第一个 FU-A 包的 FU indicator 应该是:F = NALU 头中的 F;NRI = NALU 头中的 NRI;Type = 28。FU header 应该是:S = 1;E = 0;R = 0;Type = NALU 头中的 Type。
  • 第二个 FU-A 包的 FU indicator 应该是:F = NALU 头中的 F;NRI = NALU 头中的 NRI;Type = 28。FU header 应该是:S = 0;E = 0;R = 0;Type = NALU 头中的 Type。
  • 第三个 FU-A 包的 FU indicator 应该是:F = NALU 头中的 F;NRI = NALU 头中的 NRI;Type = 28。FU header 应该是:S = 0;E = 1;R = 0;Type = NALU 头中的 Type。

Q:版主,我依照你的方法分好包发送了,发现VLC不会呈现不能解帧的情况了, 可是,仍是出不来图画。我想或许是由于发送序列参数集和图画参数集的方法不对,他们两个的长度都很小,只需一个包就可以了,我现在将他们依照singal NALU的方法发送,便是直接在NALU包前加一个RTP的头,然后发出去。 是不是我这样发参数集存在着问题,横竖我这边VLC是解不了这个参数集,由于参数集解不了,所以下面的帧必定解不了,所以出不了图画。 费事版主再解释一下怎么发参数集。

A:今天刚接受了流媒体的相关训练。懂得看你的 SDP 了。

关于你的问题,不知道 SPS、PPS 打包是否有问题。依照 RFC3984,而且感觉你打单一包的方法也是错的。我期望你能经过自己学习的方法去把这个问题弄清楚,由于 RFC3984 里边说得很清楚,请你自己学习学习 RFC3984 吧。已然你在做这个作业,仍是应该细心学习一下 RFC3984。

别的, SDP 中的 sprop-parameter-ets=Z0IACpZTBYmI 实践便是 SPS 和 PPS 的 BASE64 转码,你不必在码流中再传输 SPS/PPS,直接从 SDP 就可以得到。

A2:

  1. SDP中现已包含SPS&PPS,码流中完全可以不必传输SPS&PPS
  2. profile-level-id=42A01E,这是SPS的最初几个字节,剩下的在sprop-parameter- ets=Z0IACpZTBYmI, aMljiA==中,BASE64编码,把“Z0IACpZTBYmI, aMljiA==”反BASE64转化回去,应该刚好是SPS&PPS的内容
  3. 打包留意,要求H.264码流不是byte stream格局的,即没有0x000001分隔,也没有刺进0x03,详细怎么生成,检查你的编码器选项。
  4. packetization-mode=1模式下,要求每个RTP中只要一个NAL单元,或许一个FU,不分段的NAL不做任何修改,直接作为RTP负 载;分段的NAL留意,NAL头不传输,有效负载从NAL头之后开端,根据NAL头的信息生成FU的头两个字节(相当于NAL头拆为两部分),详细生成方 式版主现已讲得很清楚。
  5. RTP的payload type要与SDP中共同,否则解的出才怪

音视频开发——解析SDP中包含的H.264的SPS和PPS串

如有其他问题可以点下方链接

传送直达↓↓↓docs.qq.com/doc/DUkNRVF…

文末

现在这个年代,想找到一份高天花板的作业,一个一致是,得先选对赛道。有些行业和范畴,终其一生的天花板也不过如此。但有的朝阳行业,你一进去就可以取得大量的机会,便是“ROI(投入产出比)”很高。

但音视频技能学起来并不容易,要懂的东西太多:音视频的收集、编码、传输、解码、烘托…等等,网上也少见体系化的资料。

现现在的音视频技能可以说无处不在。未来,也将作为一种基础技能应用到更广泛的的场景中,音视频技能人才也会成为新宠儿。虽然很难精通,但这个范畴常识更新慢,学的东西不容易淘汰,堆集的经历将会是撬动你更大未来的一个支点。