热门标签 | HotTags
当前位置:  开发笔记 > 开发工具 > 正文

直播2----FLV文件结构解析

FLV文件结构解析FLV(FLASHVIDEO),是一种常用的文件封装格式,目前国内外大部分视频分享网站都是采用的这种格式。其标准定义为《AdobeFlashVideoFile

FLV文件结构解析

FLV(FLASH VIDEO),是一种常用的文件封装格式,目前国内外大部分视频分享网站都是采用的这种格式。其标准定义为《Adobe Flash Video File Format Specification》。RTMP协议也是基于FLV视频格式的。


FLV的文件格式在该规范中已阐述清楚,本章节不再重复描述,而是结合下面的示例具体阐述如何分析FLV文件。


图1. FLV文件结构示例1


图2. FLV文件结构示例2


FLV文件的分析工具有很多,这里给大家推荐FLV Parser这个小软件,通过它可以很容易的看到文件的组成结构。


1.1 文件结构

从整个文件上看,FLV是由Header和File Body组成,如下图所示:


图3. FLV文件总体结构


1.  FLV Header - 长度为9,其结构的标准定义参见       标准定义见E.2 The FLV header;    

2.  FLV File Body - 由一连串的PreviousTagSize +     Tag构成。previousTagSize是4个字节的数据,表     示前一个tag的size。标准定义参见E.3 The FLV     File Body。


以图1. FLV文件结构示例1为例分析整体结构:


1.  位置0x00000000 - 0x00000008, 共9个字节,为     FLV Header,其中:

 • 0x00000000 - 0x00000002 : 0x46 0x4C 0x56分    别表示字符'F''L''V',用来标识这个文件是FLV格式    的。在做格式探测的时候,如果发现前3个字节为     “FLV”,就认为它是FLV文件;

 • 0x00000003 : 0x01, 表示FLV版本号;

 • 0x00000004 : 0x05, 转换为2进制是00000101,      其中第0位为1,表示存在video,第2位为1,表示存    在audio;

 • 0x00000005 - 0x00000008 : 0x00 0x00 0x00      0x09,转十进制为9,表示FLV header的长度,当      FLV 版本号为1时,该值通常为9。


2.  位置0x00000009 - ,为FLV File Body:

 • 0x00000009 - 0x0000000C : 0x00 0x00 0x00      0x00 PreviousTagSize0,转十进制为0,该值永远    为0;

 • 0x0000000D - 0x00000209 : 0x12 ... 0x09,共       509个字节,为Tag1的具体内容;

 • 0x0000020A - 0x0000020D : 0x00 0x00 0x01       0xFD,转十进制为509,表示它前面的Tag,即         Tag1的长度为509;

 • 0x0000020E - :按照Tag + PreviousTagSize的结     构依次递推,此处不再举例说明。



1.2 Tag定义

FLV File Body是由一系列的PreviousTagSize + Tag组成,其中PreviousTagSize的长度为4个字节,用来表示前一个Tag的长度;Tag里面的数据可能是video、audio或者scripts,其定义参见E.4.1 FLV Tag,结构如下:


图4. FLV Tag 结构


以图1. FLV文件结构示例1为例分析Tag结构:


1.  位置0x0000020E : 0x08, 二进制为0000 1000,     第5位为0, 表示为非加扰文件;低5位01000为8,       说明这个Tag包含的数据类型为Audio;

2.  位置0x0000020F - 0x00000211 : 0x00 0x00         0x04,转十进制为4,说明Tag的内容长度为4,与     该tag后面的previousTagSize(15) - 11相同;

3.  位置0x00000212 - 0x00000214 : 0x00 0x00         0x00,转十进制为0,说明当前Audio数据的时间戳     为0;

4.  位置0x00000215 : 0x00,扩展时间戳为0,如果扩     展时间戳不为0,那么该Tag的时间戳应为:             Timestamp | TimestampExtended<<24;

5.  位置0x00000216 - 0x00000218 : 0x00 0x00         0x00,StreamID,总是0;

6.  StreamID之后的数据每种格式的情况都不一样,       下面会依次进行详细解读。


1.3 Audio Tags

如果TAG包中的TagType等于8,表示该Tag中包含的数据类型为Audio。StreamID之后的数据就是AudioTagHeader,其定义详见E.4.2.1 AUDIODATA。结构如下:


图5. FLV Audio Tag结构


需要说明的是,通常情况下AudioTagHeader之后跟着的就是AUDIODATA数据了,但有个特例,如果音频编码格式为AAC,AudioTagHeader中会多出1个字节的数据AACPacketType,这个字段来表示AACAUDIODATA的类型:

•  0 = AAC sequence header

•  1 = AAC raw。


以图1. FLV文件结构示例为例分析AudioTag结构:

1.  位置0x00000219 : 0xAF, 二进制表示为1010         1111:

    高4位为1010,转十进制为10,表示Audio的编码格     式为AAC;

    第3、2位为11,转十进制为3,表示该音频的采样     率为44KHZ;

    第1位为1,表示该音频采样点位宽为16bits;

    第0位为1,表示该音频为立体声。

2.  位置0x0000021A : 0x00,十进制为0,并且Audio     的编码格式为AAC,说明AACAUDIODATA中存放     的是AAC sequence header;

3.  位置0x0000021B - 0x0000021C : AUDIODATA     数据,即AAC sequence header。


1.3.1 AudioSpecificConfig

AAC sequence header中存放的是AudioSpecificConfig,该结构包含了更加详细的音频信息,《ISO-14496-3 Audio》中的1.6.2.1 章节对此作了详细定义。

通常情况下,AAC sequence header这种Tag在FLV文件中只出现1次,并且是第一个Audio Tag,它存放了解码AAC音频所需要的详细信息。

有关AudioSpecificConfig结构的代码解析,可以参考ffmpeg/libavcodec/mpeg4audio.c中的avpriv_mpeg4audio_get_config方法。

为什么AudioTagHeader中定义了音频的相关参数,我们还需要传递AudioSpecificConfig呢?


因为当SoundFormat为AAC时,SoundType须设置为1(立体声),SoundRate须设置为3(44KHZ),但这并不意味着FLV文件中AAC编码的音频必须是44KHZ的立体声。播放器在播放AAC音频时,应忽略AudioTagHeader中的参数,并根据AudioSpecificConfig来配置正确的解码参数。


1.4  Video Tag

如果TAG包中的TagType等于9,表示该Tag中包含的数据类型为Video。StreamID之后的数据就是VideoTagHeader,其定义详见E.4.3.1 VIDEODATA,结构如下:


图6. FLV Video Tag结构


VideoTagHeader之后跟着的就是VIDEODATA数据了,但是和AAC音频一样,它也存在一个特例,就是当视频编码格式为H.264的时候,VideoTagHeader会多出4个字节的信息,AVCPacketType和CompositionTime。


•  AVCPacketType用来表示VIDEODATA的内容

•  CompositonTime相对时间戳,如果                    AVCPacketType=0x01,为相对时间戳,其它均为    0;


以图2. FLV文件结构示例2为例分析VideoTagHeader结构:


1.  位置0x0000022C : 0x17, 二进制表示为0001         0111:

•  高4位为0001,转十进制为1,表示当前帧为关键       帧;

•  低4位为0111,转十进制为7,说明当前视频的编码     格式为AVC。


2.  位置0x0000022D : 0x00,十进制为0,并且Video     的编码格式为AVC,说明VideoTagBody中存放的     是AVC sequence header;


3.  位置0x0000022E - 0x00000230 : 转十进制为0,     表示相对时间戳为0;


4.  位置0x00000231 - 0x0000021C : VIDEODATA     数据,即AVC sequence header。


1.4.1   AVCDecoderConfigurationRecord

AVC sequence header中存放的是AVCDecoderConfigurationRecord,《ISO-14496-15 AVC file format》对此作了详细定义。它存放的是AVC的编码参数,解码时需设置给解码器后方可正确解码。


通常情况下,AVC sequence header这种Tag在FLV文件中只出现1次,并且是第一个Video Tag。


有关AVCDecoderConfigurationRecord结构的代码解析,可以参考中的ff_isom_write_avcc方法。


1.4.2 CompositionTime(相对时间戳)

相对时间戳的概念需要和PTS、DTS一起理解:

•  DTS : Decode Time Stamp,解码时间戳,用于告    知解码器该视频帧的解码时间;

•  PTS : Presentation Time Stamp,显示时间戳,用    于告知播放器该视频帧的显示时间;

•  CTS : Composition Time Stamp,相对时间戳,用    来表示PTS与DTS的差值。


如果视频里各帧的编码是按输入顺序依次进行的,则解码和显示时间相同,应该是一致的。但在编码后的视频类型中,如果存在B帧,输入顺序和编码顺序并不一致,所以才需要PTS和DTS这两种时间戳。视频帧的解码一定是发生在显示前,所以视频帧的PTS,一定是大于等于DTS的,因此CTS=PTS-DTS。


FLV Video Tag中的TimeStamp,不是PTS,而是DTS,视频帧的PTS需要我们通过DTS + CTS计算得到。


为什么Audio Tag不需要CompositionTime呢?

因为Audio的编码顺序和输入顺序一致,即PTS=DTS,所以它没有CompositionTime的概念。


1.5 Script Data Tags

如果TAG包中的TagType等于18,表示该Tag中包含的数据类型为SCRIPT。


SCRIPTDATA 结构十分复杂,定义了很多格式类型,每个类型对应一种结构,详细可参考E.4.4 Data Tags


onMetaData是SCRIPTDATA中一个非常重要的信息,其结构定义可参考E.5 onMetaData。它通常是FLV文件中的第一个Tag,用来表示当前文件的一些基本信息: 比如视音频的编码类型id、视频的宽和高、文件大小、视频长度、创建日期等。


推荐阅读
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 最近学习反射机制的时候Properties.load(读取本地文件流的时候怎么也找不到加载文件后面发现IDEA的默认根目录是在它的Project工程下IDEA的文件目录和Ec ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • Linuxchmod目录权限命令图文详解在Linux文件系统模型中,每个文件都有一组9个权限位用来控制谁能够读写和执行该文件的内容。对于目录来说,执行位的作用是控制能否进入或者通过 ... [详细]
  • 本文介绍了brain的意思、读音、翻译、用法、发音、词组、同反义词等内容,以及脑新东方在线英语词典的相关信息。还包括了brain的词汇搭配、形容词和名词的用法,以及与brain相关的短语和词组。此外,还介绍了与brain相关的医学术语和智囊团等相关内容。 ... [详细]
  • Java实战之电影在线观看系统的实现
    本文介绍了Java实战之电影在线观看系统的实现过程。首先对项目进行了简述,然后展示了系统的效果图。接着介绍了系统的核心代码,包括后台用户管理控制器、电影管理控制器和前台电影控制器。最后对项目的环境配置和使用的技术进行了说明,包括JSP、Spring、SpringMVC、MyBatis、html、css、JavaScript、JQuery、Ajax、layui和maven等。 ... [详细]
  • IB 物理真题解析:比潜热、理想气体的应用
    本文是对2017年IB物理试卷paper 2中一道涉及比潜热、理想气体和功率的大题进行解析。题目涉及液氧蒸发成氧气的过程,讲解了液氧和氧气分子的结构以及蒸发后分子之间的作用力变化。同时,文章也给出了解题技巧,建议根据得分点的数量来合理分配答题时间。最后,文章提供了答案解析,标注了每个得分点的位置。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 本文讨论了如何在不使用SearchBar display controller的情况下,单独使用SearchBar并捕获其textChange事件。作者介绍了实际状况,即左侧SliderMenu中的SearchBar需要在主页TableView中显示搜索结果。然后,作者提供了解决方案和步骤,帮助读者实现这一功能。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
author-avatar
zoey小
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有