将h.264视频流封装成flv格式文件(一.flv格式)

原帖地址:http://blog.csdn.net/yeyumin89/article/details/7932368


原帖虽然贵为好贴,看感觉看起来有点乱,没有层次感,贴过来,修改下格式,阅读起来方便。

一、综述:

flv文件的格式其实网上资料还是不少,但是怎么封装成flv却不多。看了不少资料,找到了一个觉得还比较靠谱的:http://www.cnblogs.com/chef/archive/2012/07/18/2597279.html

其实flv还是挺简单的一个视频格式,下面就来先谈一谈FLV的格式吧。

FLV是一个二进制文件,简单来说,其是由一个文件头(FLV header)和很多tag组成(FLV body)。

tag可以分成三类:audio,video,script,分别代表音频流,视频流,脚本流。

每个tag由tag header和tag data组成。


二、FLV header + FLV body

1. flv header (9个字节)

 

前3个bytes是文件类型,总是“FLV”,也就是(0x46 0x4C 0x56)。

第4btye是版本号,目前一般是0x01。

第5byte是流的信息,倒数第一bit是1表示有视频(0x01),倒数第三bit是1表示有音频(0x4),有视频又有音频就是0x01 | 0x04(0x05),其他都应该是0。

最后4bytes表示FLV 头的长度

2.FLV body 

       FLV header后面就是FLV body,FLV body由若干个tag 组成。

       每个tag由pre tag size(4Byte)  +  tag header(11Byte) + tag data  3部分组成。

2.1 pre tag size (4字节):

      代表上一个tag的长度。

2.2 tag header(11字节):

      第1个byte为记录着tag的类型,音频(0x8),视频(0x9),脚本(0x12);

      第2到4bytes是数据区的长度,也就是tag data的长度;

      再后面3个bytes是时间戳,单位是毫秒,类型为0x12则时间戳为0,时间戳控制着文件播放的速度,可以根据音         视频的帧率类设置;

      时间戳后面一个byte是扩展时间戳,时间戳不够长的时候用;

      最后3bytes是streamID,但是总为0。

      tag header 长度为1+3+3+1+3=11。


     例如:

     此tag为script类型的header

    

 

2.3 tag data

2.3.1 音频数据类型:

第一个byte记录audio信息:08

前4bits表示音频格式(全部格式请看官方文档):

·0 -- 未压缩

·1 -- ADPCM

·2 -- MP3

·4 -- Nellymoser 16-kHz mono

·5 -- Nellymoser 8-kHz mono

·A -- AAC

下面两个bits表示samplerate:

·0 -- 5.5KHz

·1 -- 11kHz

·2 -- 22kHz

·3 -- 44kHz

下面1bit表示采样长度:

·0 -- snd8Bit

·1 -- snd16Bit

下面1bit表示类型:

·0 -- sndMomo

·1 -- sndStereo

之后是数据。


2.3.2 视频数据类型:

第一个byte记录video信息:09

前4bits表示类型:

·1-- keyframe

·2 -- inner frame

·3 -- disposable inner frame (h.263 only)

·4 -- generated keyframe

后4bits表示解码器ID:

·2 -- seronson h.263

·3 -- screen video

·4 -- On2 VP6

·5 -- On2 VP6 with alpha channel

·6 -- Screen video version 2

·7 -- AVC (h.264)

之后是数据。

 

如果是AAC和AVC的音视频,则在放入数据前有一个音频和视频的配置信息需要写入前两个tag,等会再说。

 2.3.3 脚本数据类型:

该类型Tag又通常被称为Metadata(元数据) Tag,会放一些关于FLV视频和音频的参数信息,如duration、width、height等。通常该类型Tag会跟在File Header后面作为第一个Tag出现,而且只有一个。

一般来说,该Tag Data结构包含两个AMF包。AMF(Action Message Format)是Adobe设计的一种通用数据封装格式,在Adobe的很多产品中应用,简单来说,AMF将不同类型的数据用统一的格式来描述。

第一个 AMF包封装字符串类型数据,用来装入一个“onMetaData”标志,这个标志与Adobe的一些API调用有,在此不细述。

第二个AMF包封装一个数组类型,这个数组中包含了音视频信息项的名称和值。具体说明如下,大家可以参照图片上的数据进行理解

第一个AMF包:

 第1个字节表示AMF包类型,一般总是0x02,表示字符串,其他值表示意义请查阅文档。

  第2-3个字节为UI16类型值,表示字符串的长度,一般总是0x000A(“onMetaData”长度)。

  后面字节为字符串数据,一般总为“onMetaData”。

第二个AMF包:

 第1个字节表示AMF包类型,一般总是0x08,表示数组。

  第2-5个字节为UI32类型值,表示数组元素的个数。

  后面即为各数组元素的封装,数组元素为元素名称和值组成的对。表示方法如下:

   第1-2个字节表示元素名称的长度,假设为L。

     后面跟着为长度为L的字符串。

     第L+3个字节表示元素值的类型。

   后面跟着为对应值,占用字节数取决于值的类型

 

 

到此flv格式的解析就差不多了,如有写错的地方请指出。

 

附上一个网友写的flv的查看工具:http://download.csdn.net/detail/yeyumin89/4534822 大笑安静

 



  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
封装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封装的基本框架,具体的实现要根据业务需求进行相应的调整和优化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值