FLV流媒体封装格式

1、FLV 简介


FLV(Flash Video) 是 Adobe 公司推出的一种流媒体格式,由于其封装后的音视频文件体积小、封装简单等特点,非常适合于互联网上使用。目前主流的视频网站基本都支持FLV。采用 FLV 格式封装的文件后缀为.flv。直播场景下拉流比较常见的是 http-flv 直播流,具有延时低,易传输等特点。

------------------------

2、FLV 格式


总体上看,FLV 由文件头(file header)和(file body)组成,其中 FLV body 由一对对的 Tag 和 Previous Tag Size(占用4个字节,记录前一个 Tag 的大小,用于逆向读取处理,FLV header 后的第一个 Previous Tag Size 为 0)组成。而 Tag 一般分为三种类型:脚本数据、视频数据、音频数据,有 Tag header 和 Tag Data 组成。FLV 数据以大端序进行存储,在解析时需要注意。一个标准 FLV 文件结构如下图:

FLV 文件的详细内容结构如下:

---------------------------

2.1 FLV header(文件头)

从上图中可以看到,FLV 头占用 9 个字节,用来标识文件类型为 FLV 类型,以及后续的音视频标识。一个 FLV 文件,每种类型的 tag 都属于一个流,也就是一个 flv 文件最多只有一个音频流,一个视频流,不存在多个独立的音视频流在一个文件的情况。FLV 头的结构如下:

上面的 UI 表示无符号整型,后面跟着的数字代表其长度是多少位;UB 表示位域,表示一个字节的多少位。可以参考C语言中的结构体位域。

------------------------------------

2.2 FLV Body(文件体)


FLV Header之后,就是 FLV File Body。FLV File Body 是由一连串的 back-pointers + tags 构成。

back-pointer
back-pointer 表示 Previous Tag Size(前一个 tag 的字节数据长度),占4个字节,
第一个 back-pointer 数据为0。

Tag
音视频数据,每一个 tag 由两部分组成:tag header 和 tag data。

----------------------------------------

3、FLV Tag 详解

3.1 Tag 数据结构

flv_tag_header + flv_tag_data,其中 flv_tag_header 占 11 个字节。

3.2 FLV_tag_header

存放当前 tag 的类型、数据区长度、时间戳等信息。tag header 一般占 11 个字节的内粗空间。

3.3 FLV_Tag_Data

FLV Tag 的类型可以是视频、音频和 Script(脚本类型)

3.3.1 Script Tag Data(脚本类型、帧类型)

脚本 Tag 一般只有一个,是 flv 的第一个 Tag,跟在 flv header 后,用于存放 flv 视频和音频的元信息,比如 duration、audiodatarate、creator、width 等。一般来说,Script Tag Data结构包含两个 AMF 包(AMF(Action Message Format)是 Adobe 设计的一种通用数据封装格式,在 Adobe 的很多产品中应用,简单来说,AMF 将不同类型的数据用统一的格式来描述),结构如下:

第一个 AMF 包(封装字符串类型数据):

第 1 个字节表示 AMF 包类型,一般总是 0x02,表示字符串; 第 2-3 个字节为 UI16 类型值,表示字符串的长度,一般总是 0x000A(“onMetaData”长度); 后面字节为字符串数据,一般总为 “onMetaData”(6F,6E,4D,65,74,61,44,61,74,61)。

---------------------------------------

第二个 AMF 包(封装一个数组类型,这个数组中包含了音视频信息项的名称和值):

第 1 个字节表示 AMF 包类型,一般总是 0x08,表示数组。 第 2-5 个字节为 UI32 类型值,表示数组元素的个数。 后面即为各数组元素的封装,数组元素为元素名称和值组成的对。表示方法如下: 第 1-2 个字节表示元素名称的长度,假设为 L。后面跟着为长度为 L 的字符串。第 L+3 个字节表示元素值的类型。后面跟着为对应值,占用字节数取决于值的类型。

常见的数组元素表示如下表:

=======================

3.3.2 Video Tag Data(视频类型)


视频 Tag Data 开始的第一个字节包含视频数据的参数信息,从第二个字节开始为视频流数据。结构如下:

第一个字节包含视频信息:前4位表示帧类型;后4位表示编码类型。

第二个字节开始为视频数据

AVC VIDEO PACKET

视频的格式(CodecID)是 AVC(H.264)的话,VideoTagHeader 会多出 4 个字节的信息,AVCPacketType 和 CompositionTime,所以是 H264 编码的情况下 VideoHeader 长度是 5 个字节。 AVC VIDEO PACKET 结构如下:

AVCDecoderConfigurationRecord

包含着 H.264 解码相关比较重要的 sps 和 pps 信息,再给 AVC 解码器送数据流之前一定要把 sps 和 pps 信息送出,否则的话解码器不能正常解码。 而且在解码器 stop 之后再次 start 之前,如 seek、快进快退状态切换等,都需要重新送一遍 sps 和 pps 的信息。 AVCDecoderConfigurationRecord 在 FLV 文件中一般情况也是出现 1 次,也就是第一个 video tag。

sps pps

第一个 video tag 一般存放的是 sps 和 pps。存储的格式: 0x01 + sps[1] + sps[2] + sps[3] + 0xFF + 0xE1 + sps size + sps + 01 + pps size + pps 其中 sps size 和 pps siz e各占两个字节。 data 数据结构:

关于 CTS:需要和 pts,dts 配合一起理解。 pts:presentation time stamps 显示时间,也就是接收方在显示器显示这帧的时间。单位为1/90000 秒; dts:decoder timestamps 解码时间,也就是rtp包中传输的时间戳,表明解码的顺序。单位为1/90000 秒。——根据后面的理解,pts 就是标准中的 CompositionTime; cts偏移:cts = (pts - dts) / 90。cts 的单位是毫秒; pts 和 dts 的时间不一样,应该只出现在含有 B 帧的情况下,也就是 profile main 以上。baseline 是没有这个问题的,baseline 的 pts 和 dts 一直相同,所以 cts 一直为 0 。

=================================

3.3.3 Audio Tag Data(音频类型)

音频 Tag Data 区域开始的第一个字节包含了音频数据的参数信息,从第二个字节开始为音频流数据。结构如下:

第一个字节包含音频信息:前 4bit 表示音频格式;第 5、6bit 表示采样率;第 7bit 表示采样精度;第 8bit 表示音频声道。

第二个字节开始为音频数据

其中如果音频格式为 10,即是 AAC 格式的,AudioTagHeader 中会多出一个字节 AACPacketType,这个字段来表示 AACAUDIODATA 的类型:0 = AAC sequence header,1 = AAC raw。

AAC sequence header 也就是包含了 AudioSpecificConfig,AudioSpecificConfig 包含着一些更加详细音频的信息。

AAC raw 这种包含的就是音频 ES 流了,也就是 audio payload。

12 00 01 17 00 00 00 00 00 00 00 (tag header 11 字节)

0x12 表示这是一个 scripts tag, 00 01 17 三子节表示 tag data 长度为 279 个字节,Timestreamp、TimestampExtended、stream id 均为0。 下一个 back-pointers,表示该 scripts tag 的 size,即 279 + 11 = 290 = 0x122,即 00 00 01 22,可以看到最后4字节刚好是的。

02 00 0a 6f 6e 4d 65 74 61 44 61 74 61 表示第一个 AMF 包,02 表示类型为 string type,后面两个字节 00 0A 表示长度是 10,值 onMetaData; 03 表示 ObjectType,此处应该一般是 08 才对,表示数组类型;表示有8个键值对。 00 05 表示键长度,77 69 64 74 68 表示 width,00 表示类型为 Number,后面 8 字节表示值; 00 06 表示键长度, 68 65 69 67 68 74 表示 height,00 表示类型为 Number,后面 8 字节表示值。 以此类推解析到最后 end marker 00 00 09,表示解析完毕。

4、举例子
根据真实数据来解析 FLV 格式。

4.1 FLV header
<464c5601 05000000 09000000 00120001 17000000 00000000 02000a6f 
6e4d6574 61446174 61030005 77696474 68004084 00000000 00000006 
68656967 68740040 7e000000 00000000 0c736f75 7263655f 77696474 
6800409e 00000000 0000000d 736f7572 63655f68 65696768 74004090 
e0000000 00000009 6672616d 65726174 6500402e 00000000 0000000c 
76696465 6f636f64 65636964 00401c00 00000000 00000f61 7564696f 
73616d70 6c657261 74650040 bf400000 00000000 0f617564 696f7361 
6d706c65 73697a65 00403000 00000000 00000673 74657265 6f010000 
0c617564 696f636f 64656369 64004024 00000000 0000000c 63726561 
74696f6e 64617465 02001732 3032312d 31312d30 33203037 3a32373a 
33302055 54430006 61757468 6f720200 034c4c4c 00000900 000122>
46 4C 56 01 05 00 00 00 09:表示 FLV header(9 字节),音视频都有; 0x 00 00 00 00 表示第一个 back-pointers(前一个 tag 的 size)。因为前面没有 tag,所以为 0。

4.2 脚本 Tag
12 00 01 17 00 00 00 00 00 00 00 (tag header 11 字节) 0x12 表示这是一个 scripts tag, 00 01 17 三子节表示 tag data 长度为 279 个字节,Timestreamp、TimestampExtended、stream id 均为0。 下一个 back-pointers,表示该 scripts tag 的 size,即 279 + 11 = 290 = 0x122,即 00 00 01 22,可以看到最后4字节刚好是的。 02 00 0a 6f 6e 4d 65 74 61 44 61 74 61 表示第一个 AMF 包,02 表示类型为 string type,后面两个字节 00 0A 表示长度是 10,值 onMetaData; 03 表示 ObjectType,此处应该一般是 08 才对,表示数组类型;表示有8个键值对。 00 05 表示键长度,77 69 64 74 68 表示 width,00 表示类型为 Number,后面 8 字节表示值; 00 06 表示键长度, 68 65 69 67 68 74 表示 height,00 表示类型为 Number,后面 8 字节表示值。 以此类推解析到最后 end marker 00 00 09,表示解析完毕。

4.3 第一个 video tag
一般包含 sps、pps

<09000022 00000000 00000017 00000000 014d401e ffe1000e 674d401e 
a680a03d a6e02020 20400100 0468ee3c 80000000 2d>
09 00 00 22 00 00 00 00 00(tag header 11 字节) 09 表示视频 tag; 00 00 22 表示长度为 0x22 = 34,加上头部长度 11 字节,为 45。下一个 back-pointers 是 00 00 00 2D(上面数据的最后的四字节), Timestreamp、TimestampExtended、stream id 均为 0; 下面就是 tag data 数据: 0x17 即 0001 0111,前 4 位表示帧类型,1 为关键帧;后 4 位表示编码 ID,7 表示 AVC。 视频格式是AVC(H.264)类型的话,后面 1 个字节表示 AVCPacketType,再后三个字节表示 CompositionTime: 00 AVCPacketType 为 0,表示是 AVCDecoderConfigurationRecord。就表示包含着 sps 和 pps 了。这个东西要第一个发给解码器,要不然不能正常解码。 00 00 00 CompositionTime 为 0。接下来就是 sps 和 pps 的信息了。 按照 0x01 + sps[1] + sps[2] + sps[3] + 0xFF + 0xE1 + sps size + sps + 01 + pps size + pps 的格式,参照二进制数据: sps[1] = 4d;sps[2] = 40;sps[3] = 1e;sps size = 000e,表示 sps 的长度为 14,14 字节的数据读取完,读到 01;pps size = 0004,表示 pps 的长度为 4,读取完后该 tag 结束。下一个back-pointers。

4.4 第二个 video tag 以及后续的 video tag

<09002374 00000000 00000017 01000000 0000236b 65b82129 7f7ae073 
74574ffe 0fd1ebcc 6851014a d25aa986 6daee3a1 6f0d7b77 734e17a9 
0fe00e56 a92b864b 3d423839 c229a2ab 23208467 ... ...00 00237f>
下一个 video 长度为 9076 的视频数据,0x17 后一位 AVCPacketType 01,表示 NALU 数据,三个 CompositionTime 字节过后,就是 NALU 数据了。

4.5 第一个 audio tag 以及后续的 audio tag

<08000004 00005d00 000000ae 00158800 00000f>

08 00 00 04         00 00 5d 00       00 00 00ae

0x08 表示音频;

00 00 04 表示长度为 4,时间戳为 93;

加上头部长度 11,为 15,下一个 back-pointers 是 0x 00 00 00 0F(最后四子节);接下来就是 tag data: AE: 即 0b10101110,前 4 位为 10,表示音频格式是 AAC;10 会多一个字节 AACPacketType,表示该 AACAUDIODATA 的类型;第 5、6 位为 11,十进制 3,表示采样率为 44kHz;第 7 位为1,表示 16 位采样精度;第 8 位为 0,表示 sndMono 单声道。 00: 表示 AACPacketType,为 0 表示该 Tag 是 AAC sequence header。接下来两个字节表示 AudioSpecificConfig,包含更加详细音频的信息。读取完后该 tag 结束。下一个 back-pointers。

4.6 第二个 audio tag 以及后续的 audio tag

<080002fb 00005d00 000000ae 01010e34 14564a2d 92154484 d0602e72 
f7cab6d6 af82156c cae24cba a6f8d2b9 d2d512d3 db8b5632 ef76c8a9 
95225c3b 69e84d7d 03a6fa66 7b475759 0ead71f5 37c73379 fd124cd5 
1ba64d95 48d7aa3b c558863e 090fc9ae ... ...0000 0306>
下一个长度为 752 的音频数据,时间戳为 93,0xae 后一位为 01,表示 ACC raw,即音频 NALU

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/499090.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

无人车网关案例:记SV900无人清扫车网关的现场应用

​随着无人驾驶技术的不断发展,无人车辆已经开始广泛应用于物流配送、环境保洁、巡逻监控等众多领域,助力城市运营更加高效智能。而要实现无人车辆的安全可靠运行,关键在于选择一款性能卓越的车载网络通信系统.在这一背景下,星创易联推出了SV900无人车网关系列产品。它集5G/4G网…

kubernetes(K8S)学习(九):K8S之日志监控

K8S之日志监控 一、Log and Monitor1.1 Log1.1.1 容器级别1.1.2 Pod级别1.1.3 组件服务级别1.1.4 LogPilot ES Kibana 1.2 Monitor1.2.1 Prometheus简介1.2.2 Prometheus架构1.2.3 Prometheus知识普及1.2.4 数据采集1.2.5 Prometheus Grafana 二、Trouble Shooting&#xff…

重生奇迹mu 弓箭手有什么技能

1、弓箭手职业技能&#xff1a;多重箭&#xff1a;同时射出三发弓箭&#xff0c;给予复数敌人伤害&#xff0c;根据弓的不同&#xff0c;射出的数量也不同。天堂之箭&#xff1a;弓箭垂直射向天际&#xff0c;准确的落在敌人的头顶上&#xff0c;造成严重的伤害。 2、重生奇迹…

【Unity】TextMeshPro富文本

启用富文本 在Unity里&#xff0c;如果需要使用富文本&#xff0c;首先需要开启Rich Text 如果不开启Rich Text&#xff0c;就会在UI上显示富文本代码 1.粗体 <b>Game</b> Over2.斜体 <i>Game</i> Over3.下划线 <u>Game</u> Over4…

ctfshow靶场sql注入wp

目录 web171 web172 web173 web174 web175 web176 web177-179 web180-183 web184 web185 web187 web190 web191 web192 web193 web194 web195 web196 web197 web199 web201 web202 web203 web204 web205 web206 web207 web208 web209 web210 web…

14 Games101 - 笔记 - 光线追踪(利用包围盒技术加速光线追踪(KD-Tree and BVH)

14 光线追踪&#xff08;利用包围盒技术加速光线追踪&#xff08;KD-Tree and BVH&#xff09; 在上一节中&#xff0c;我们介绍了whited-style光线追踪的原理&#xff0c;以及实现细节。相比与光栅化中所使用的的Blinn-Phong模型&#xff0c;光线追踪显著了提升了图像质量&am…

uniapp实现的数据选择器,支持H5、微信小程序

采用uniapp-vue3实现的数据选择器&#xff0c;支持H5、微信小程序&#xff08;其他小程序未测试过&#xff0c;可自行尝试&#xff09; 支持本地自定义过滤、远程接口过滤&#xff0c;为了避免弹窗面板超出边界的情况&#xff0c;自动计算弹窗面板安置的位置&#xff08;在微信…

Java八股文(设计模式)

Java八股文の设计模式 设计模式 设计模式 什么是设计模式&#xff1f;请列举一些常见的设计模式。 设计模式是软件设计中常用的一种思维模式&#xff0c;它描述了一类具有相似特征和解决思路的问题。 常见的设计模式包括单例模式、工厂模式、观察者模式、装饰器模式等。 请解释…

博士推荐 | 拥有8年以上的材料和电池开发经验的电池材料专家

编辑 / 木子 审核 / 朝阳 伟骅英才 伟骅英才致力于以大数据、区块链、AI人工智能等前沿技术打造开放的人力资本生态&#xff0c;用科技解决职业领域问题&#xff0c;提升行业数字化服务水平&#xff0c;提供创新型的产业与人才一体化服务的人力资源解决方案和示范平台&#x…

2024 年多链代币开发对您的业务有何好处

2024 年&#xff0c;多链代币开发将成为寻求增强数字化影响力并释放区块链领域新机遇的企业的关键战略。通过利用多个区块链&#xff0c;公司可以显着提高其代币的可扩展性、互操作性和安全性。这种方法不仅提高了交易速度并降低了费用&#xff0c;还使企业能够利用更广泛的用户…

港大新工作 HiGPT:一个模型,任意关系类型 !

论文标题&#xff1a; HiGPT: Heterogeneous Graph Language Model 论文链接&#xff1a; https://arxiv.org/abs/2402.16024 代码链接&#xff1a; https://github.com/HKUDS/HiGPT 项目网站&#xff1a; https://higpt-hku.github.io/ 1. 导读 异质图在各种领域&#xf…

编译与链接(想了解编译与链接,那么看这一篇就足够了!)

前言&#xff1a;在我们练习编程的时候&#xff0c;我们只需要将代码写入、运行&#xff0c;就可以得到计算之后的结果了&#xff0c;但是你有没有想过&#xff0c;为什么就可以得到计算之后的结果呢&#xff0c;它的底层又到底是什么呢&#xff1f; ✨✨✨这里是秋刀鱼不做梦的…

气象预测新篇章:Python人工智能的变革力量

Python是功能强大、免费、开源&#xff0c;实现面向对象的编程语言&#xff0c;在数据处理、科学计算、数学建模、数据挖掘和数据可视化方面具备优异的性能&#xff0c;这些优势使得Python在气象、海洋、地理、气候、水文和生态等地学领域的科研和工程项目中得到广泛应用。可以…

数据结构与算法分析2栈、队列

1.栈和队列本质上都是表&#xff0c;所以他们都有两种实现方式&#xff0c;链表实现和数列实现。栈的特点是后进先出。 2.栈的实现 3.应用有&#xff1a; 4.栈的危险操作&#xff1a;用尽栈空间&#xff0c;导致内容占用到别的寄存器里面去了&#xff0c;从而出现异常。还有尾…

武汉星起航:借亚马逊平台优势助力商家精准营销

在全球经济一体化的背景下&#xff0c;跨境电商已成为推动国际贸易发展的重要引擎。作为跨境电商领域的佼佼者&#xff0c;亚马逊平台以其全球化销售渠道和强大的数据分析能力&#xff0c;为商家提供了前所未有的商机。武汉星起航电子商务有限公司深知亚马逊平台的优势&#xf…

企业为什么要用MES管理系统来升级改造生产车间

随着信息技术的迅猛发展&#xff0c;工业制造领域正经历着深刻的变革。在这个大背景下&#xff0c;MES管理系统的引入和应用&#xff0c;已成为企业升级改造生产车间、提升竞争力的关键手段。本文将从多个维度探讨企业为何要用MES管理系统来升级改造生产车间。 MES管理系统能够…

查询优化-提升子查询-UNION类型

瀚高数据库 目录 文档用途 详细信息 文档用途 剖析UNION类型子查询提升的条件和过程 详细信息 注&#xff1a;图片较大&#xff0c;可在浏览器新标签页打开。 SQL: SELECT * FROM score sc, LATERAL(SELECT * FROM student WHERE sno 1 UNION ALL SELECT * FROM student…

云计算——大模型应用发展的“理想支点”

在数字化浪潮中&#xff0c;人工智能技术的突飞猛进为千行百业带来了前所未有的转型机遇。近期出现的Sora模型能够根据文本描述生成高质量的视频内容&#xff0c;为多领域带来大模型技术飞跃的冲击。如何推进大模型应用&#xff0c;已成为各行业面临的重要课题之一。 打造硬核…

亚信安慧AntDB数据库分布式架构剖析之snapshot sender进程

本文主要介绍亚信安慧AntDB数据库的分布式架构下的特有进程之snapshot sender进程的设计&#xff0c;与snapshot receiver进程是一对&#xff0c;也是分布式架构的核心进程之一。 进程简介 与Snapshot Receiver进程相对应&#xff0c;该进程的作用从整体上看也只包含两个方面&a…

Shopee 4月市场趋势及选品分析,shopee虾皮品类爆款预测

废话不多说&#xff0c;马上进入本周Shopee“现象爆品”、“热门爆品趋势”及“热搜词周榜"版块&#xff0c;帮助商家及时了解Shopee最新市场现状&#xff0c;掌握选品趋势。 1 现象爆品 近几来&#xff0c;为健康“买单”&#xff0c;已经成为全年龄层群体的“刚需”。 图…