关闭

FLV 实例分析

标签: flv
2928人阅读 评论(0) 收藏 举报
分类:

上一篇文章我们就FLV文件格式做了一个分析,这篇文章,我们结合实际的FLV文件对照着FLV的结构来一一分析一遍。

我们用UltraEdit打开一个FLV文件,我们看到的内容大概是这样的:
FLV_header

FLV Header

其中选中的9个字节就是FLV header 我们通过最右边的字符表述可以很清楚的知道。
头三个字节 0x46 0x4C 0x56 正好是FLV三个字母的ASCII码的值。
接下来的一个字节 0x01 就是Version字段。对于FLV版本是1
第五个字节0x05 用二进制表达就是 ‘0101’b。也就是
TypeFlagsAudio = 1
TypeFlagsVideo= 1
表明这个文件包含音频流和视频流。
第六个字节但第九个字节为 0x00000009 大端模式,所以值就是9。与协议一致。就是FLV header结构的字节长度。

接下来的就是FLV File Body了,第一个四字节是PreviousTagSize0。我们看到是 0x00000000。因为在这个字段之前是没有TAG的,所以固定为0。

好了,现在FLV Header + PreviousTagSize0 = 13 Bytes。也就是从第十四个字节开始就会是我们的第一个FLV TAG了。
我们先来一张FLV TAG的结构图
FLVTAG
我先取到前面十一个字节的内容

FLVTAG
第一个字节的内容是0x12 我们转换为二进制就是 ‘0001 0010’。 看得到,前三个位是0。意味着Filter ==0;
也就是TagType == 0x12 表示成10进制就是 18 (script data)。就是说这是一个脚本Tag。
后面三个字节对应DataSize == 0x0002A9 。我们把它转换为十进制数是 681。注意DataSize的定义。是StreamID之后的数据长度。所以整个TAG的长度应该是681 + 11 = 692。从地址 0x0000000D 到 0x000002C0

SCRIPTTAG

图片中被选中的内容就是这个ScriptTAG的内容。
因为TagType == 18所以Data字段的内容就是 SCRIPTDATA
SCRIPTTAGBODY
第一个域是Name。Name又是SCRIPTDATAVALUE类型
SCRIPTDATAVALUE_1
SCRIPTDATAVALUE_2
第一个字节Type。
Type == 0x02, String 类型
ScriptDataValue 是SCRIPTDATASTRING类型。

SCRIPTDATASTRING
然后再接下来的两个字节是后面的String的长度。 StringLength == 0x000A , 10个字节。
StringData的内容是 0x6F 0x6E 0x4D 0x65 0x74 0x61 0x44 0x61 0x74 0x61 也就是 “onMetaData”。
再接下来一个字节又是Type。Type ==0x08 对应的数据类型是 SCRIPTDATAECMAARRAY
SCRIPTDATAECMAARRAY
0x08 后面是 ECMAArrayLength == 0x00000019。 所以这个数组长度为 25。
ECMAArrayLength后面就是SCRIPTDATAOBJECTPROPERTY类型的数字。长度25。
SCRIPTDATAOBJECTPROPERTY
PropertyName 是SCRIPTDATASTRING类型,先看前两字节
Length == 0x000F。15个字节。所以这个PropeotyName就是
metadatacreator
对应的值是 “metadatacreator”。
PropertyData是一个SCRIPTDATAVAULE类型。
Type ==0x02。ScriptDataString类型。
StringLength == 0x0003。三个字节。
StringData == 0x696B75。“iku”。

接下来看第二个SCRIPTDATAOBJECTPROPERTY
PropertyName.StringLength == 0x000C。长度为12
PropertyName.StringData == “68 61 73 4B 65 79 66 72 61 6D 65 73”H : hasKeyframes
PropertyData.Type== 0x01。Boolean
PropertyData.ScriptDataValue==0x01。表示有KeyFrames信息。

**这里我们boolean型 0x01定义为yes,boolean型的0x00 定义为no。
到现在我们得到的Propertys有
metadatacreator = “iku”
hasKeyFrames = yes

接下来我就不一个一个分析了。直接把这里所以的Propertys的结果列出来
metadatacreator = “iku”
hasKeyFrames = yes
hasVideo = yes
hasAudio = yes
hasMetadata = yes
canSeekToEnd = no
dutation = 0x 40 41 0B 22 D0 E5 60 42(double 类型) (34.087 Secends)
datasize = 0x 41 2C 78 54 00 00 00 00 (double 类型) (932906.0 bytes)
videosize =0x 41 28 0B 34 00 00 00 00 (double 类型) (787866.0 bytes)
videocodecid = 0x401C000000000000 (7.0) (AVC)
width = 0x4080000000000000 (512.0)
height =0x4072000000000000 (288.0)
framerate = 0x402DFB6B354139DD (14.99) 也就是15帧每秒
videodatarate = 0x4066691F064D11D2 (179.28kbps)
audiosize = 0x410118A000000000 (140052.0 bytes)
audiocodecid = 0x4024000000000000 (10.0) (AAC)
audiosamplerate = 0x 40 E5 88 80 00 00 00 00(44100.0 kHz)
audiosamplesize = 0x4030000000000000 (16.0 bits)
stereo = yes
audiodatarate = 0x403E3E4E7394F6F6 (30.24kbps)
filesize = 0x412C7DDE00000000 (933615.0 bytes)
lasttimestamp = 0x40410B22D0E56042 (34.087)
lastkeyframtimestamp = 0x403E000000000000 (30.0)
lastkeyframlocation = 0x412B0DC400000000 (886498.0)
keyframes.propertyName = filepositions
keyframs.filepositions.StrictArrayLength = 0x00 00 00 07 (数组大小为7)
keyframs.filepositions[0] =0x4086280000000000 709.0
keyframs.filepositions[1] = 0x4088C80000000000 793.0
keyframs.filepositions[2] = 0x41073B3800000000 190311.0
keyframs.filepositions[3] = 0x411740D400000000 380981.0
keyframs.filepositions[4] = 0x412129DA00000000 562413.0
keyframs.filepositions[5] = 0x41269FE800000000 741364.0
keyframs.filepositions[6] = 0x412B0DC400000000 886498.0
keyframs.times.StrictArrayLength = 0x00 00 00 07 (数组大小为7)
keyframs.times[0] = 0x 00 00 00 00 00 00 00 00 (0.0)
keyframs.times[1] = 0x 00 00 00 00 00 00 00 00 (0.0)
keyframs.times[2] = 0x4018000000000000 (6.0)
keyframs.times[3] = 0x 40 28 00 00 00 00 00 00 (12.0)
keyframs.times[4] = 0x 40 32 00 00 00 00 00 00 (18.0)
keyframs.times[5] = 0x 40 38 00 00 00 00 00 00 (24.0)
keyframs.times[6] = 0x 40 3E 00 00 00 00 00 00 (30.0)

注: 这里的double的值都是通过 Floating Point to Hex Converter 这个在线工具计算得出的。

最后的几个字节内容是结束符。再后面四个字节是PreviousTagSize
firstTagEnd
可以看到
previousTagSize = 0x 0002b4 = 692 正好与我们前面计算的ScriptTag的长度一致。至此,第一个FLVTAG分析完了。然后我们获得了很大信息。从onMetaData这个Script TAG中。

接下来的就是VidoeTag: 从第一个字节 0x09 获知TagType = video。
我们先取从 0x000002C5 开始的11个字节的内容。
firstVdieoFLVTAGheader
解析之后对应字段的值如下:
Filter = 0;
TagType = 9 (Video)
DataSize = 0x00002D (45) 也就是从0x000002D0 开始后的45个字节是这个TAG余下的内容。到0x000002FC。
Timestamp = 0
TimestampExtended = 0
StreamID = 0

videoHeader

通过前TagType == 9 我们已经确定了是视频TAG,那么接着StreamID字段之后的就是VideoTAagHeader
VideoTagHeader
先看第一个字节的内容吧
第一个字节是 0x17。即
FrameType= 0x01
CodecID = 0x07
因为CodecID == 7。所以这个时候会多出两个字段 AVPacketType 和CompositionTime。两字段共四个字节。
解析出来的值分别是:
AVCPacketType = 0 ;说明后面的内容是AVC sequence header
CompositionTime = 0;

当AVCPacketType == 0 CodecID== 7 的时候。那么VideoTagBody的 Type是 AVCVIDEOPACKET 类型
AVCVIDEOPACKET
也就是这个时候应该是一个AVCDecoderConfigurationRecord结构
AVCDecoderConfigurationRecord
configurationVersion = 0x01
AVCProfileIndication = 0x4D (77) Main Profile
profile_compatibiltity = 0x40
AVCLevelIndication = 0x1F (31)
第五六字节是0xFFE1 ,写成二进制格式 ‘1111 1111 11110 00001’b
对应到AVCDecoderConfigurationRecord的语法定义
lengthSizeMinusOne = ‘11’b (3) 也就是NALUintLength字段会是4个字节
numOfSequenceParameterSets = ‘00001’b 有一个Sps结构
接下来16bits 是 sequenceParameterSetLength = 0x0019 (25 bytes)
下图选中部分就是Sps了
Sps

再往下:
numOfPictureParamterSets = 0x01
pictureParameterSetLength = 0x0004;
下图选中的就是pps了
pps
再后面四个字节是PreviousTagSize= 0x00 00 00 38 (56) 等于这个Tag的 DataSize + 11 == (45) + 11。

再下来又是一个新的FLVTAG了。
11个字节的头部先取出来
audioFLVTag

TagType = 8 (音频)
DataSize =0x000009 ( 9bytes)
audiotagData
开头是一个AudioTagHeader结构
SoundFormat(4bits) = 0x0A (10 == AAC)
SoundRate(2bits) = ‘11’b (3 == 44kHz)
SoundSize(1bit) =’1’b (1 == 16-bit)
SoundType(1bit) = ‘1’b (1= Stereo)
注: 虽然这里SoundRate, SoundSize SoundType 都是 1 。但是这些都是定值,AAC格式的时候,不看这里的值,可以忽略掉。具体的真是值应该从后面的数据从获取
AACPacketType == 0x00 (AAC seqence header)
所以AACPacketType后面的就是AudioSpecificConfig了 0x13 90 56
AudioSpecificConfig.audioObjectType(5 bits) = 2 (AAC LC)
AudioSpecificConfig.samplingFrequencyIndex(4 bits) = 7
AudioSpecificConfig.channelConfiguration (4 bits)= 2
AudioSpecificConfig.GASpecificConfig.frameLengthFlag (1 bit) = 0
AudioSpecificConfig.GASpecificConfig.dependsOnCoreCoder : (1 bit) = 0
AudioSpecificConfig.GASpecificConfig.extensionFlag : (1 bit) = 1
剩下的四个字节就是extensionflag3的相关内容,这块还没有研究过。
到这一个audioTag结束。
后面的0x00000014是这个AudioTag的长度 等于 20 = 9 + 11。
再后面又是一个新的TAG。
VideoTag1
从这前11个字节知道的是这是一个视频Tag. DataSize = 0x00099F (2463)timeStamp == 0;
然后再往后看,是一个VideoTagHeader结构,可以得到的信息如下
FrameType = 1 (是一个Key Frame)
CodecID= 7 (AVC)
AVCPacketType = 1 ;是一个普通的AVC NALUint
CompositionTime = 0x000043 (67)
然后从0x00000329 —— 0x00000CC2 就是一个完整的 Key Frame的数据了。
那么这个Key Frame包含多少个NALUint呢,我们再来一步步看下去吧。记得前面我们分析的吗?NALUint数据的开头的NALUintLength字段。由之前的分析可知。占四个字节,

NALUintLength0
NALUintLength = 0x00000222 (546 Bytes) 说明第一NALUint的长度是546字节
从0x0000032D —— 0x0000054E
NALUint0

接着是第二个NALUintLength = 0x00 00 05 F3 (1523 bytes)
从0x00000553 —— 0x00000B45

NALUint1_0
NALUint1_1

接下来又是一个NALUintLength = 0x00 00 01 0B (267 bytes)
从0x00000B4A —— 0x00000C54

NALUint2

下来又是一个NALUintLenth = 0x00 00 00 32 (50 bytes)
从0x00000C59 —— 0x00000C8A

NALUint3

接下来还是一个NALUintLength = 0x00 00 00 34 (52 byte)
从 0x00000C8F —— 0x00000CC2

NALUint4

好了,到这里我们第一个KeyFrame的所有NALUint都已经取出来了
TagDataSize (2463 Bytes)= 1 (FrameType + CodecID) + 1 (AVCPacketType) + 3 (CompositionTime) + 4 + 546 +4 + 1523 + 4 + 267 + 4 + 50 + 4 + 52
等式成立。

这个VidoeTag后面是四字节的PreviousTagSize = 0x00 00 09 AA = 0x00 00 09 9F + 0x0B;

再往回又是一个TAG了。先取开头11个字节
AudioTAG
解析一次,我们可以知道
TagType = 8;
DataSize = 0x 00 00 27 (39bytes)
Timestamp= 0
所以余下的AudioTag的内容从 0x00000CD2 —— 0x00000CF8
AudioTagBody0
分析可得以下信息
SoundFormat = 0x0A (10 AAC)
SoundRate= 1
SoundSize =1
SoundType =1
AACPacketType = 1 (AAC raw data)
所以AAC raw data为下图所示
AACRawData0

再往下分析又是一个AudioTag 从0x00000CF8 —— 0x00000DC0
AudioTag2
这个AudioTag的 DataSize = 0xB9 (185 byte) 除去 0xAF01 这两个字节的AudioTagHeader。
AAC raw data有185 字节
Timestamp = 0x00002E
TimestempExtended = 0x00
总起来TimeStampOffset = 0x0000002E ( 46 milcoSecends)

再后面是一个视频帧了 从0x00000DC5 —— 0x00001EA8
DataSize == 0x00 10 D9
Timetamp = 0x00 00 43 (67)
TimestampExtended = 0x00
videoTag2_start


videoTag2_end

我们稍微分析下这个Tag的VideoTagHeader吧
FrameType= 2 (inter Frame, for AVC a non-seekable frame)
CodecID = 7
AVCPacketType =1 (AVC NALU)
CompositionTime = 0x00010A (266)
NALUintLength0 = 0x000008AE (2222Bytes)
NALUint0 到 0x00001686结束
NALUintLength1 = 0x00000188 (392 bytes)
NALUint1 到 0x00001812 结束
NALUintLength2 = 0x00000513 (1299 bytes)
NALUint2 到0x00001D29 结束
NALUint3Length = 0x00 00 01 7B(379 Bytes)
NALUint3 到 0x00001EA8 结束 (这里正好是这个videoTag的结尾)

好了,后面就不再分析下去了。基本就是这个节奏一直走先去就能分析到文件的结尾了。

0
0
查看评论

FLV文件格式——实例分析

http://blog.csdn.net/tianyue168/article/details/5994962 版权声明:本文为博主原创文章,未经博主允许不得转载。 一 .FLV文件头  FLV文件开始处是一个FLV头。  FLV头(FLV header)&...
  • STN_LCD
  • STN_LCD
  • 2017-06-27 09:18
  • 208

FLV文件结构解析

1. FLV文件格式相对于MP4,简单很多。    FLV Header(9Bytes) + FLV Body                ...
  • huibailingyu
  • huibailingyu
  • 2015-01-19 19:55
  • 1957

用ffmpeg转换flv至mpeg

原贴:http://linuxdesktop.cn/2007/07/25/ffmpeg-convert-flv-to-mpeg 用ffmpeg转换flv至mpeg 2007-07-25 13:50 | 分类 影音图像 | By TualatriX | 315 次阅读 在YouTube上...
  • chinalinuxzend
  • chinalinuxzend
  • 2007-10-17 00:51
  • 7639

FLV格式的解复用和PTS分析代码

视频解码研究之PTS(1)TS格式和FLV格式 视频解码研究之PTS(2)Mp4格式,AVI格式和MKV格式 在视频解码研究之PTS(1)TS格式和FLV格式中分析了FLV格式PTS,并提供了程序运行结果,这里给出代码。这段代码能够打印flv格式中所有的PTS,还...
  • qq_32430349
  • qq_32430349
  • 2016-12-21 16:43
  • 665

打包AAC码流到FLV文件

AAC编码后数据打包到FLV很简单。 1. FLV音频Tag格式                               字节位置  ...
  • huibailingyu
  • huibailingyu
  • 2016-01-21 11:49
  • 2810

FLV帧全面分析。研究心得。

本文转载自:http://blog.csdn.net/peijiangping1989/article/details/6999224 做视频会议,用RTMP协议,就要把视频流封装成flv包。 最近几星期一直在纠结怎么封装,终于让我找到规律了。 首先下载一个flvparse软件。来...
  • Jody1989
  • Jody1989
  • 2015-05-28 09:12
  • 1050

flv 解封装

#include #include #include #define DEBUG_INFO typedef struct FileHeader { unsigned char type[4]; // UI8 * 3 "FLV" unsigned cha...
  • zhengfl
  • zhengfl
  • 2014-03-27 18:14
  • 582

实例分析神经网络传播过程

神经网络简介 博客主要内容 神经网络框架 神经网络前向传播实例 神经网络反向传播实例 总结 引用 一.神经网络简介今天,神经网络(nerual networks)已经是一个相当大的、多学科交叉的学科领域[1]。它不能用简单的用“一个算法”,“一个框架”,来总结它的内容。从早期神经元(neuron),...
  • u013139259
  • u013139259
  • 2016-11-01 23:03
  • 581

在Flash中播放flv视频

 采用ActionScript3.0脚本实现flv视频的播放,需要用一系列类的协作:你需要一个NetStream对象来加载视频和控制视频的播放;然而NetStream类只处理流动数据,它并不处理数据的显示,因此需要一个Video对象使用NetStream数据在屏幕上显示视频。NetStre...
  • Anglewing_nwpu
  • Anglewing_nwpu
  • 2007-06-06 22:38
  • 1095

flv 协议解析 (学习记录)

FLV(Flash Video)是现在非常流行的流媒体格式,由于其视频文件体积轻巧、封装播放简单等特点,使其很适合在网络上进行应用,目前主流的视频网站无一例外地使用了FLV格式。另外由于当前浏览器与Flash Player紧密的结合,使得网页播放FLV视频轻而易举,也是FLV流行的原因之一。 ...
  • CodySnow
  • CodySnow
  • 2015-12-30 16:52
  • 1998
    个人资料
    • 访问:52757次
    • 积分:790
    • 等级:
    • 排名:千里之外
    • 原创:23篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    博客专栏
    文章分类