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

前面写了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
  • 4
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 26
    评论
封装H.264/H.265裸流为FLV格式,需要进行以下几个步骤: 1. 准备好H.264/H.265裸流数据,注意需要满足FLV封装规范。FLV格式将视频数据和音频数据分别封装在不同的Tag内。 2. 构造FLV文件头,设置FLV的版本号、是否包含音频/视频、数据偏移量等参数。 3. 构造音频Tag和视频Tag。对于视频Tag,需要设置帧类型(关键帧或非关键帧)、编码ID、时间戳、数据大小等参数;对于音频Tag,需要设置声道数、采样率、采样精度、编码ID、时间戳、数据大小等参数。 4. 将FLV文件头和音视频Tag写入到输出流中,即可生一个FLV格式的媒体文件。 下面是一个Java NIO实现的示例代码: ```java import java.io.File; import java.io.FileOutputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class FlvPackager { private static final int FLV_HEADER_SIZE = 9; private static final int TAG_HEADER_SIZE = 11; private FileChannel outChannel; private ByteBuffer buffer; private long timestampBase; public FlvPackager(String filename) throws Exception { File file = new File(filename); if (file.exists()) { file.delete(); } this.outChannel = new FileOutputStream(file).getChannel(); this.buffer = ByteBuffer.allocate(1024 * 1024); this.timestampBase = System.currentTimeMillis(); writeFlvHeader(); } public void writeVideoTag(byte[] data, boolean keyframe) throws Exception { int dataSize = data.length; long timestamp = System.currentTimeMillis() - timestampBase; buffer.clear(); buffer.put((byte) 0x09); buffer.putInt(dataSize + TAG_HEADER_SIZE); buffer.putInt((int) timestamp & 0xFFFFFF); buffer.put((byte) ((timestamp >> 24) & 0xFF)); buffer.putInt(0); buffer.put((byte) (keyframe ? 0x10 : 0x17)); buffer.put(data); buffer.flip(); outChannel.write(buffer); } public void writeAudioTag(byte[] data) throws Exception { int dataSize = data.length; long timestamp = System.currentTimeMillis() - timestampBase; buffer.clear(); buffer.put((byte) 0x08); buffer.putInt(dataSize + TAG_HEADER_SIZE); buffer.putInt((int) timestamp & 0xFFFFFF); buffer.put((byte) ((timestamp >> 24) & 0xFF)); buffer.putInt(0); buffer.put((byte) 0xAF); buffer.put(data); buffer.flip(); outChannel.write(buffer); } public void close() throws Exception { outChannel.close(); } private void writeFlvHeader() throws Exception { buffer.clear(); buffer.put((byte) 'F'); buffer.put((byte) 'L'); buffer.put((byte) 'V'); buffer.put((byte) 0x01); buffer.put((byte) 0x05); buffer.putInt(FLV_HEADER_SIZE); buffer.putInt(0); buffer.flip(); outChannel.write(buffer); } } ``` 使用示例: ```java FlvPackager packager = new FlvPackager("test.flv"); byte[] videoData = ...; // H.264/H.265裸流 byte[] audioData = ...; // AAC裸流 packager.writeVideoTag(videoData, true); // 关键帧 packager.writeAudioTag(audioData); ... packager.close(); ``` 以上代码仅提供了一个FLV封装的基本框架,具体的实现要根据业务需求进行相应的调整和优化。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值