[时间:2016-07] [状态:Open]

FLV是一个相对简单的多媒体格式,仅支持单节目,也就是说每个FLV只能至多一个音频、至多一个视频。FLV(Flash Video)是Adobe的一个免费开放的音视频格式。由于在流媒体中应用比较多,还是可以简单了解下的。

这是说明下,F4V和FLV格式不太一样,建议不要混淆了。具体的可以参考下标准文档。整体来说,F4V是FLV的升级版,解析起来跟MP4有点类似,复杂很多,但是功能更复杂。

0. 学习多媒体容器格式的目的

主要是为了回答以下问题:

  1. 该容器中数据是如何组织的?
  2. 该容器包含哪些编码格式的数据?这些数据是如何存储的?
  3. 该容器包含哪些元数据信息?包含哪些节目信息?
  4. 对于支持多节目的容器格式,如何找到对应的音频流、视频流、字幕流?
  5. 如何确定该容器的节目播放时长?
  6. 如何从该容器中提取音频、视频、字幕数据,并交给解码器解码,有时间戳否?
  7. 该容器是否支持seek?有哪些辅助信息?
  8. 是否支持直接流化?
  9. 哪里可以找到该容器格式最标准的文档资料?
  10. 有哪些可用的工具,方便分析容器格式异常或者错误?

1. FLV整体结构

FLV从整体来看包括两大部分:header和body。

header中主要用于辨识文件的标志以及版本号,以及音视频是否存在。

body是Flv的数据区域,这些是FLV的具体内容,因为FLV中的内容有多种,并可同时存在,因此,Body也不是一整块的数据,而是由更细分的块来组成,这个细分的块叫Tag。

总体上来说,其结构是这个样子的:

===================
header
-------------------
prev tag size
-------------------
tag 0
-------------------
prev tag size
-------------------
………………………
-------------------
tag N
-------------------
prev tag size
===================

在这里可以把header作为一个特殊的tag,这个tag只能出现在flv文件头中。下面依次看一下各部分的字段定义。

注意FLV中所有字段都是按照大端存储的,比如258(0x0102),按照字节序存储应该是0x01、0x02。

2. FLV header

FLV header总共9个字节,其具体含义如下表所示:

Field Type Comment
Signature UI8 Signature byte always 'F' (0x46)
Signature UI8 Signature byte always 'L' (0x4C)
Signature UI8 Signature byte always 'V' (0x56)
Version UI8 File version (for example, 0x01 for FLV version 1)
TypeFlagsReserved UB[5] Must be 0
TypeFlagsAudio UB[1] Audio tags are present
TypeFlagsReserved UB[1] Must be 0
TypeFlagsVideo UB[1] Video tags are present
DataOffset UI32 Offset in bytes from start of file to startof body (that is, size of header)

前三个字节是文件标志,FLV的文件标志为固定的“FLV",字节(0x46, 0x4C,0x56),这个可以用于唯一识别FLV文件。

第四个字节是文件版本号,具体含义可以参考标准文件。

TypeFlagsAudio和TypeFlagsVideo分别标志当前文件是否存在音频、视频。

最后一个字段,DataOffset是用于标识body的起始位置,其长度大小为header长度,主要是为了后续扩展header使用。

注意上表中UB表示二进制,UB[n]表示n bit数据长度。

下面看一下一段比较典型FLV header的二进制码流:

46 4c 56 01 05 00 00 00 09

前三个字节是FLV,文件版本号为1,TypeFlagsAudio和TypeFlagsVideo均是1,表示音视频都有,DataOffset是9。

3. FLV body

FLV header之后紧跟着就是body。标准中推荐使用DataOffset字段读取FLV body的偏移位置,这里面记录了所有的音频、视频、脚本等数据。

其构成如下:

Field Type--- Comment
PreviousTagSize0 UI32 Always 0
Tag1 FLVTAG First tag
PreviousTagSize1 UI32 Size of previous tag, including its header, in bytes. For FLV version 1, this value is 11 plus the DataSize of the previous tag.
Tag2 FLVTAG Second tag
... ... ...
PreviousTagSizeN-1 UI32 Size of second-to-last tag, including its header, in bytes.
TagN FLVTAG Last tag
PreviousTagSizeN UI32 Size of last tag, including its header, in bytes.

除了第一个TagSize为0外,其他的一般都不是0。每一个PreviousTagSize都是其上一个FlvTag的DataSize+固定偏移。这样就可以通过TagSize实现快速的逆序访问文件。

FLV Tag中有VideoTag、AudioTag、ScriptTag三种,可以通过标志位区分,其结构定义如下:

Field Type Comment
Reserved UB[2] Reserved for FMS, should be 0
Filter UB[1] Indicates if packets are filtered.
0 = No pre-processing required.
1 = Pre-processing (such as decryption) of the packet is required before it can be rendered.
Shall be 0 in unencrypted files, and 1 for encrypted tags.
TagType UB[5] Type of contents in this tag. The following types are defined:
8 = audio
9 = video
18 = script data
DataSize UI24 Length of the message. Number of bytes after StreamID to end of tag (Equal to length of the tag – 11)
Timestamp UI24 Time in milliseconds at which the data in this tag applies. This value is relative to the first tag in the FLV file, which always has a timestamp of 0.
TimestampExtended UI8 Extension of the Timestamp field to form a SI32 value. This field represents the upper 8 bits, while the previous Timestamp field represents the lower 24 bits of the time in milliseconds.
StreamID UI24 Always 0.
AudioTagHeader IF TagType == 8 AudioTagHeader AudioTagHeader element
VideoTagHeader IF TagType == 9 VideoTagHeader VideoTagHeader element
EncryptionHeader IF Filter == 1 EncryptionTagHeader Encryption header shall be included for each protected sample
FilterParams IF Filter == 1 FilterParams FilterParams shall be included for each protected sample
Data IF TagType == 8 AUDIODATA
IF TagType == 9 VIDEODATA
IF TagType == 18 SCRIPTDATA
Data specific for each media type.

从上面表格中可以看出在StreamID之前的字段都是通用的,这11个字节,可以认为是TagHeaderInfo。

第1字节:其中5 bit,TagType标志当前Tag的类型,音频(0x08),视频(0x09),Script Data(0x12),除此之外,其他值非法;

第2-4字节:表示一个无符号24位整型数值,表示当前Tag Data的大小;

第5-7字节:无符号24位整型数值(UI24),当前Tag的时间戳(单位为ms),第一个Tag的时间戳总为0;

第8字节:为时间戳的扩展字节,当前24位不够用时,该字节作为最高位,将时间戳扩展为32位无符号整数(UI32);

第9-11字节:UI24类型,表示Stream ID,总是0。

后面的数据对应的包括Tag header和实际负载数据。

Audio Tag

当TagType=8时,当前Tag是音频数据,包含AudioTagHeader和AudioData。AudioTagHeader通常是1-2个字节,各字段含义如下(这里仅列出常用的,更详细的建议参考FLV标准文件):

Field Type---- Comment
SoundFormat UB[4] Format of SoundData. The following values are defined:
0 = Linear PCM, platform endian
2 = MP3
10 = AAC
AAC is supported in Flash Player 9,0,115,0 and higher.
SoundRate UB[2] Sampling rate. The following values are defined:
0 = 5.5 kHz
1 = 11 kHz
2 = 22 kHz
3 = 44 kHz
SoundSize UB[1] Size of each audio sample. This parameter only pertains to uncompressed formats. Compressed formats always decode to 16 bits internally.
0 = 8-bit samples
1 = 16-bit samples
SoundType UB[1] Mono or stereo sound
0 = Mono sound
1 = Stereo sound
AACPacketType IF SoundFormat == 10
UI8
The following values are defined:
0 = AAC sequence header
1 = AAC raw

很明显,这里面记录了音频编码类型、采样率、量化位数,对于AAC编码,还会包含额外的sequence header。

接下来的AudioData需要按照实际音频编码格式解析,格式并不固定。

Video Tag

当TagType=9时,当前Tag是视频数据,包含VideoTagHeader和VideoData。VideoTagHeader通常是1字节或者5字节,各字段含义如下(这里仅列出常用的,更详细的建议参考FLV标准文件):

Field Type--------------- Comment
Frame Type UB[4] Type of video frame. The following values are defined:
1 = key frame (for AVC, a seekable frame)
2 = inter frame (for AVC, a non-seekable frame)
3 = disposable inter frame (H.263 only)
4 = generated key frame (reserved for server use only)
5 = video info/command frame
CodecID UB[4] Codec Identifier. The following values are defined:
2 = Sorenson H.263
3 = Screen video
4 = On2 VP6
5 = On2 VP6 with alpha channel
6 = Screen video version 2
7 = AVC
AVCPacketType IF CodecID == 7
UI8
The following values are defined:
0 = AVC sequence header
1 = AVC NALU
2 = AVC end of sequence (lower level NALU sequence ender is not required or supported)
CompositionTime IF CodecID == 7
SI24
IF AVCPacketType == 1
  Composition time offset
ELSE
  0
See ISO 14496-12, 8.15.3 for an explanation of composition times. The offset in an FLV file is always in milliseconds.

VideoTagHeader中记录了帧类型和视频编码方式,这样就可以根据视频编码类型来确定如何解析VideoData字段。其具体含义如下:

IF FrameType == 5
UI8
ELSE (
IF CodecID == 2
H263VIDEOPACKET
IF CodecID == 3
SCREENVIDEOPACKET
IF CodecID == 4
VP6FLVVIDEOPACKET
IF CodecID == 5
VP6FLVALPHAVIDEOPACKET
IF CodecID == 6
SCREENV2VIDEOPACKET
IF CodecID == 7
AVCVIDEOPACKET
)

在FrameType=5时,Tag里面保存的不再是视频负载数据,而是一个字节的字段,表示seeking开始和结束,具体取值含义如下:

0 = Start of client-side seeking video frame sequence

1 = End of client-side seeking video frame sequence

对于具体每个数据包的解析,建议参考FLV和swf标准文档中的说明。

Script Tag

Script Tag包含的负载数据是ScriptTagBody类型,里面的SCRIPTDATA编码为AMF(Action Message Format)。ScriptTagBody由Name和Value两个字段组成(类型均为SCRIPTDATAVALUE)。那么SCRIPTDATAVALUE如何定义的,见下表:

Field Type--------------- Comment
Type UI8 Type of the ScriptDataValue. The following types are defined:
0 = Number
1 = Boolean
2 = String
3 = Object
4 = MovieClip (reserved, not supported)
5 = Null
6 = Undefined
7 = Reference
8 = ECMA array
9 = Object end marker
10 = Strict array
11 = Date
12 = Long string
ScriptDataValue IF Type == 0
 DOUBLE
IF Type == 1
 UI8
IF Type == 2
 SCRIPTDATASTRING
IF Type == 3
 SCRIPTDATAOBJECT
IF Type == 7
 UI16
IF Type == 8
 SCRIPTDATAECMAARRAY
IF Type == 10
 SCRIPTDATASTRICTARRAY
IF Type == 11
 SCRIPTDATADATE
IF Type == 12
 SCRIPTDATALONGSTRING
Script datavalue.
The Boolean value is (ScriptDataValue ≠ 0).

onMetaData

FLV的metadata存储在名为onMetaData的SCRIPTDATA,里面有很多字段,可以通过下表看到:

Property Name Type Comment
audiocodecid Number Audio codec ID used in the file (see AudioTagHeader for available SoundFormat values)
audiodatarate Number Audio bit rate in kilobits per second
audiodelay Number Delay introduced by the audio codec in seconds
audiosamplerate Number Frequency at which the audio stream is replayed
audiosamplesize Number Resolution of a single audio sample
canSeekToEnd Boolean Indicating the last video frame is a key frame
creationdate String Creation date and time
duration Number Total duration of the file in seconds
filesize Number Total size of the file in bytes
framerate Number Number of frames per second
height Number Height of the video in pixels
stereo Boolean Indicating stereo audio
videocodecid Number Video codec ID used in the file (see VideoTagHeader for available CodecID values)
videodatarate Number Video bit rate in kilobits per second
width Number Width of the video in pixels

4. 其他问题

从上面介绍中可以知道FLV是单节目的,不会有多节目流的选择,其格式解析非常简单,甚至看不到专门的索引表。

如何确定该容器的节目播放时长?

节目时长只能通过onMetaData中的duration解析。

如何从该容器中提取音频、视频、字幕数据,并交给解码器解码,有时间戳否?

这里只强调下时间戳信息,在每个Tag的开头都有时间戳信息,是可以通过两个域计算的。

哪里可以找到该容器格式最标准的文档资料?

Adobe官网有提供FLV、SWF的标准文档,具体可以查看本文的参考文献

有哪些可用的工具,方便分析容器格式异常或者错误?

比较经典的分析工具主要是FLVParser

参考文献

  1. 分析flv文件的信息
  2. FLV文件格式详解
  3. SWF and AMF Technology Center
  4. F4V/FLV Technology Center

多媒体文件格式之FLV的更多相关文章

  1. 多媒体文件格式(一):MP4 格式

    在互联网常见的格式中,跨平台最好的应该就属MP4文件了.因为MP4文件既可以在PC平台的Flashplayer中播放,又可以在移动平台的Android.iOS等平台中进行播放,而且使用系统默认的播放器 ...

  2. 多媒体文件格式分析 MP3文件结构及编解码流程

    多媒体文件格式分析 http://blog.csdn.net/taniya001/article/details/7962864 多媒体文件格式分析 MP3文件结构及编解码流程 http://www. ...

  3. 多媒体文件格式(二):FLV 格式

    在网络的直播与点播场景中,FLV也是一种常见的格式,FLV是Adobe发布的一种可以作为直播也可以作为点播的封装格式,其封装格式非常简单,均以FLVTAG的形式存在,并且每一个TAG都是独立存在的,接 ...

  4. 多媒体文件格式之MKV

    [时间:2016-07] [状态:Open] MKV是一种开源的多媒体封装格式,是Matroska中应用比较多的格式之一.常见的后缀格式是.mkv(视频,包括音频和字幕)..mka(纯音频)..mks ...

  5. 用java程序调用ffmpeg执行视频文件格式转换flv

    用java小例题说明更直观:(可以直接编译运行)环境我在windows平台下测试的...需要在e:/下有ffmpeg.exe;mencoder.exe;drv43260.dll;pncrt.dll共4 ...

  6. 多媒体文件格式之AVI

    [时间:2016-07] [状态:Open] AVI(Audio Video Interleaved的缩写)是一种RIFF(Resource Interchange File Format的缩写)文件 ...

  7. 多媒体文件格式之RMVB

    [时间:2016-07] [状态:Open] RM/RMVB是Real公司私有的封装格式,常见的后缀形式是rm.ra.rmvb. 通常封装的都是real转悠的编码格式,比如音频中的sipro.cook ...

  8. 多媒体文件格式之MP4

    [时间:2016-06] [状态:Open] 学习多媒体容器格式的目的 主要是为了回答以下问题: 该容器中数据是如何组织的? 该容器包含哪些编码格式的数据?这些数据是如何存储的? 该容器包含哪些元数据 ...

  9. 多媒体文件格式之ASF

    [时间:2016-06] [状态:Open] ASF,全称Advanced Systems Format,是由微软提出的开放封装格式标准.ASF是微软公司Windows Media的核心.这是一种包含 ...

随机推荐

  1. jsp空指针异常

    1.Tomcat启动后访问首页报错 显示JSP 空指针异常 这哥们是因为lib下jar包和Tomcat下的jar包冲突,去掉lib下 servlet-api-2.5.jar 以及jsp-api.jar ...

  2. HDU 1556 Color the ball (数状数组)

    Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  3. 收集一些常用Javascripot

    获取一组单选框当前选择值: $("input[name='radGende']:checked").val();

  4. FluentScheduler

    The job configuration is handled in a Registry class. A job is either an Action or a class that inhe ...

  5. 【Algorithm】快速排序(续)

    前面在常用的排序算法中,已经写过一篇关于快速排序算法的博客,但是最近看到<The C Programming Language>这本书中的快速排序算法写的不错,所以就拿过来分享一下,下面我 ...

  6. 初步了解pandas(学习笔记)

    1 pandas简介 pandas 是一种列存数据分析 API.它是用于处理和分析输入数据的强大工具,很多机器学习框架都支持将 pandas 数据结构作为输入. 虽然全方位介绍 pandas API ...

  7. mysql 创建函数问题

    ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declar ...

  8. mysql homedir迁移

    随着数据库的增长,innodb文件和日志文件会越来越大,如果是默认安装的mysql,这些文件一般是放在 /usr/lib/mysql 下面进行转移: 1,安全关闭mysql mysqladmin -u ...

  9. mysqldump: Couldn't execute 'SET OPTION SQL_QUOTE_SHOW_CREATE=1'

    源码安装的mysql数据库,在执行mysqldump的时候报错: # mysqldump -u root -p --all-databases > dbdump.db Enter passwor ...

  10. 【转】对 Rust 语言的分析

    对 Rust 语言的分析 Rust 是一门最近比较热的语言,有很多人问过我对 Rust 的看法.由于我本人是一个语言专家,实现过几乎所有的语言特性,所以我不认为任何一种语言是新的.任何“新语言”对我来 ...