将h.264视频流封装成flv格式文件(二.开始动手)

11 篇文章 0 订阅

前面写了flv文件的解析,有h264裸流的话就开始封装吧。网上大多数都是用ffmeg库来做这个工作的,哎,学习资料少学不会,还是自己动手吧。

封装前要先了解下h.264格式,只需要知道一点点就可以了,我看了h.264官方文档,我靠,3百多页,还全是中文,什么,是中文?既然是中文的我就勉强看下吧,我靠,看起来还很复杂的,果断不看了,不需要,也没时间,我又不做解码,这东西具体步骤资料又少,基本都是那一两篇转来转去,这还要感谢我上一篇提到的那个连接的兄弟,记录下过程,不然以后就忘干净了。
 
h264是一个个NALU单元组成的,每个单元以00 00 01 或者 00 00 00 01分隔开来,每2个00 00 00 01之间就是一个NALU单元。我们实际上就是将一个个NALU单元封装进FLV文件
 
每个NALU单元开头第一个byte的低5bits表示着该单元的类型,即NAL nal_unit_type:
#define NALU_TYPE_SLICE 1
#define NALU_TYPE_DPA 2
#define NALU_TYPE_DPB 3
#define NALU_TYPE_DPC 4
#define NALU_TYPE_IDR 5
#define NALU_TYPE_SEI 6          
#define NALU_TYPE_SPS 7
#define NALU_TYPE_PPS 8
#define NALU_TYPE_AUD 9
#define NALU_TYPE_EOSEQ 10
#define NALU_TYPE_EOSTREAM 11
#define NALU_TYPE_FILL 12
每个NALU第一个byte & 0x1f 就可以得出它的类型,比如上图第一个NALU:67 & 0x1f = 7,则此单元是SPS,第三个:68 & 0x1f = 8,则此单元是PPS
 
前一章说到如果数据是AAC或者AVC的话,则有一个音频和视频的配置信息需要写入前两个tag(metadata之后),AAC音频就不说了,在ISO-14496-3 Audio 中有描述,给一张图。
 
说下AVC视频流的configuretion,ISO-14496-15 AVC file format 有详细描述,先给两张图,一张是说明,一张是实际截图。
 

   上面这个图的内容,乍一看起来好像明白,但是如果没有某一个例子对照的话,再仔细看的时候就会一头雾水,那么我们该用哪个例子来和他对照呢??当然是没有例子,因为原来的作者就没有配图,还是我自己配一个图吧,见下图(上图中的01 42 E0 14是原作者的例子的内容,我们这个例子中的内容是01 64 00 28)

看这个这个图,再对照上面的那个说明图,就好理解了,也就是说,在第一个真正的视频帧之前,还是有一个编码说明帧的,这一帧,或者叫这一tag里面的内容,来源于我们的sps和pps两部分的组合。只要有了这个,我们就可以保证保存下来的flv文件的可使用性了。这也是我自己的血的教训啊,保存的flv一直不能播放,郁闷死了。。。
 
这个例子是对应我第一个截图来的,一般h264数据最开始的两个NALU就是PSP和PPS,但是我现在还没有明白为什么我的那个h264裸流在开始的时候会有两个SPS、PPS,而且之后数据还会不时的出现,但是我没有管这个,依然只各弄了一个进去,其他的忽略掉了,反正多余的我都忽略了,也没发现有什么错。反正首先把音视频的配置信息封进metadata之后的tag,然后就可以封数据了。再说下元数据,flv header之后就是它了,再之后就是音视频配置信息,再后面就是音视频数据,元数据前一章说了是amf格式的,安格式封就行了,测试其实没有元数据视频也可以正常播放,等会再简单说下amf吧。
 
 
现在开始封装h264数据吧,前一章提到了flv关于AVC的格式,除开元数据,其他数据是:一个byte的video信息+一个byte的AVCPacket type+3个bytes的无用数据(composition time,当AVC时无用,全是0)+ 4个bytes的NALU单元长度 + N个bytes的NALU数据,所以包头数据长度信息是刚才提到的信息的总和长度。要强调下,当音视频配置信息tag的时候,是没有4个bytes的NALU单元长度的
AVC的配置信息时,先上一个图,
17 -- 高4bits:1,keyframe。 低4bits:7,代表AVC。 后面一个byte 0x00,AVCPacket type,代表AVC sequence header。后3个bytes无意义,之后就是decoder configuration record的内容了。 图中绿底部分后面紧跟的8byte:00 00 00 28就是前面tag的总长度
 
当NALU第一个byte xx & 0x1f == 5的时候,说明该单元是一个I frame,关键帧
17 -- 和上面的一样。 01 -- AVC NALU。蓝色框内的4个bytes记录后面NALU数据的长度。65 & 0x1f == 5.
 
如果NALU第一个byte xx & 0x1f != 5的时候,就不是一个I frame
27 -- 高4bits:2,inter frame ,P frame。 低4bits:7,AVC NALU。其他都一样。图中绿底部分后面紧跟的8byte:00 00 00 19就是前面tag的总长度。
 
 
整个的flv文件其实是:FLV header + previous tag size0 + tag1 + previous tag size1 + tag2 + previous tag size2 + ... +tagN + previous tag sizeN。
tag1是metadata,记录视频的一些信息;tag2是视频配置信息(AVC decoder configuration record),tag3是音频配置信息(如果没有音频则去掉此项),tag4以及之后的tag就是音视频数据了。
每一个结构怎么封都说清楚了,安上面的步骤一个一个NALU封就行了。
 
 
 
 
封包的时候要特别注意一下包头里面的时间戳,因为这个控制着播放的速度,如果不填,全是0的话,播放会相当快,一般按视频帧率来设置。我这个h264流是8帧的,所以我每个tag的时间间隔是125ms左右。
注意了,flv里面的数据都是大端模式,放数据进去要转换一下,如果你是通常的小端的机器的话。
 
 
 
 
到这里应该差不多了吧,我是一个NALU单元封装成一个tag,我也是刚接触,不知道上述还有哪些地方不合理,不过测试没有发现问题。我也才接触这东西,如果有知情人,望解释一下为什么有多个PPS SPS,谢谢可怜
 
至于rtmp协议发送flv,之后再写吧。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值